您的位置:首页 > 其它

【CF】196 Div.2 D. Book of Evil

2015-07-11 20:47 477 查看
显然这个图是一课树,看着题目首先联想到LCA(肯定是可以解的)。但是看了一下数据大小,应该会TLE。
然后,忽然想到一个前面做过的题目,大概是在一定条件下树中某结点旋转成为根后查询最长路径。
结果灵感就来了,主要思路是对于每个结点,第一次dfs得到两个变量到P结点的最大值以及次大值。
然后,第二次dfs对于当前结点u,u到它的子树中P类结点的最大距离已知(nd[u].mx),那么除u的其他结点v到P类结点的最大距离加上v到u的距离和的最大值为pmx,可以通过每次深搜计算出来,只要d大于等于两者的最大值就为有效结点。而pmx的求法也很容易,对于u来说pmx可能为其父亲的pmx+1,或者为v的兄弟结点的mx值。
刚好因为我们已知每个结点的最大值以及次大值,所有兄弟结点的最大值可求。直接用INT_MIN,实现比较容易。

/* 337D */
#include <iostream>
#include <string>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
#include <deque>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
#include <climits>
#include <cctype>
#include <cassert>
#include <functional>
#include <iterator>
#include <iomanip>
using namespace std;
//#pragma comment(linker,"/STACK:102400000,1024000")

#define sti                set<int>
#define stpii            set<pair<int, int> >
#define mpii            map<int,int>
#define vi                vector<int>
#define pii                pair<int,int>
#define vpii            vector<pair<int,int> >
#define rep(i, a, n)     for (int i=a;i<n;++i)
#define per(i, a, n)     for (int i=n-1;i>=a;--i)
#define clr                clear
#define pb                 push_back
#define mp                 make_pair
#define fir                first
#define sec                second
#define all(x)             (x).begin(),(x).end()
#define SZ(x)             ((int)(x).size())
#define lson            l, mid, rt<<1
#define rson            mid+1, r, rt<<1|1

typedef struct {
int mx, mx2;
} node_t;

const int maxn = 1e5+5;
bool mark[maxn];
int n, m, d;
vi E[maxn];
node_t nd[maxn];
int ans = 0;

int dfs(int u, int fa) {
int i, v;
int tmp;

nd[u].mx = nd[u].mx2 = INT_MIN;
if (mark[u])
nd[u].mx = 0;
for (i=0; i<SZ(E[u]); ++i) {
v = E[u][i];
if (v != fa) {
tmp = dfs(v, u) + 1;
if (tmp >= nd[u].mx) {
// find the two fathest distance from p[*] to u
nd[u].mx2 = nd[u].mx;
nd[u].mx = tmp;
} else if (tmp > nd[u].mx2) {
nd[u].mx2 = tmp;
}
}
}

// -1 means no p in the path
return nd[u].mx;
}

void dfs2(int u, int fa, int pmx) {
int i, v;
int tmp = max(pmx, nd[u].mx);

if (tmp <= d) {
++ans;
}
for (i=0; i<SZ(E[u]); ++i) {
v = E[u][i];
if (v != fa) {
if (nd[v].mx+1 == nd[u].mx)
tmp = nd[u].mx2;
else
tmp = nd[u].mx;
tmp = max(tmp, pmx)+1;
dfs2(v, u, tmp);
}
}
}

int main() {
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif

int u, v;

scanf("%d %d %d", &n, &m, &d);
while (m--) {
scanf("%d", &u);
mark[u] = true;
}

rep(i, 1, n) {
scanf("%d %d", &u, &v);
E[u].pb(v);
E[v].pb(u);
}

// get the item in node
dfs(1, -1);
// calculate the number of valid position
dfs2(1, -1, INT_MIN);

printf("%d\n", ans);

#ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: