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

时间:2023-03-10 03:42:33
【CF】196 Div.2 D. Book of Evil

显然这个图是一课树,看着题目首先联想到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+;
bool mark[maxn];
int n, m, d;
vi E[maxn];
node_t nd[maxn];
int ans = ; 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 = ;
for (i=; i<SZ(E[u]); ++i) {
v = E[u][i];
if (v != fa) {
tmp = dfs(v, u) + ;
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=; i<SZ(E[u]); ++i) {
v = E[u][i];
if (v != fa) {
if (nd[v].mx+ == nd[u].mx)
tmp = nd[u].mx2;
else
tmp = nd[u].mx;
tmp = max(tmp, pmx)+;
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, , n) {
scanf("%d %d", &u, &v);
E[u].pb(v);
E[v].pb(u);
} // get the item in node
dfs(, -);
// calculate the number of valid position
dfs2(, -, INT_MIN); printf("%d\n", ans); #ifndef ONLINE_JUDGE
printf("time = %d.\n", (int)clock());
#endif return ;
}