【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,实现比较容易。
1 /* 337D */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm> 11 #include <cstdio> 12 #include <cmath> 13 #include <ctime> 14 #include <cstring> 15 #include <climits> 16 #include <cctype> 17 #include <cassert> 18 #include <functional> 19 #include <iterator> 20 #include <iomanip> 21 using namespace std; 22 //#pragma comment(linker,"/STACK:102400000,1024000") 23 24 #define sti set<int> 25 #define stpii set<pair<int, int> > 26 #define mpii map<int,int> 27 #define vi vector<int> 28 #define pii pair<int,int> 29 #define vpii vector<pair<int,int> > 30 #define rep(i, a, n) for (int i=a;i<n;++i) 31 #define per(i, a, n) for (int i=n-1;i>=a;--i) 32 #define clr clear 33 #define pb push_back 34 #define mp make_pair 35 #define fir first 36 #define sec second 37 #define all(x) (x).begin(),(x).end() 38 #define SZ(x) ((int)(x).size()) 39 #define lson l, mid, rt<<1 40 #define rson mid+1, r, rt<<1|1 41 42 typedef struct { 43 int mx, mx2; 44 } node_t; 45 46 const int maxn = 1e5+5; 47 bool mark[maxn]; 48 int n, m, d; 49 vi E[maxn]; 50 node_t nd[maxn]; 51 int ans = 0; 52 53 int dfs(int u, int fa) { 54 int i, v; 55 int tmp; 56 57 nd[u].mx = nd[u].mx2 = INT_MIN; 58 if (mark[u]) 59 nd[u].mx = 0; 60 for (i=0; i<SZ(E[u]); ++i) { 61 v = E[u][i]; 62 if (v != fa) { 63 tmp = dfs(v, u) + 1; 64 if (tmp >= nd[u].mx) { 65 // find the two fathest distance from p[*] to u 66 nd[u].mx2 = nd[u].mx; 67 nd[u].mx = tmp; 68 } else if (tmp > nd[u].mx2) { 69 nd[u].mx2 = tmp; 70 } 71 } 72 } 73 74 // -1 means no p in the path 75 return nd[u].mx; 76 } 77 78 void dfs2(int u, int fa, int pmx) { 79 int i, v; 80 int tmp = max(pmx, nd[u].mx); 81 82 if (tmp <= d) { 83 ++ans; 84 } 85 for (i=0; i<SZ(E[u]); ++i) { 86 v = E[u][i]; 87 if (v != fa) { 88 if (nd[v].mx+1 == nd[u].mx) 89 tmp = nd[u].mx2; 90 else 91 tmp = nd[u].mx; 92 tmp = max(tmp, pmx)+1; 93 dfs2(v, u, tmp); 94 } 95 } 96 } 97 98 int main() { 99 ios::sync_with_stdio(false); 100 #ifndef ONLINE_JUDGE 101 freopen("data.in", "r", stdin); 102 freopen("data.out", "w", stdout); 103 #endif 104 105 int u, v; 106 107 scanf("%d %d %d", &n, &m, &d); 108 while (m--) { 109 scanf("%d", &u); 110 mark[u] = true; 111 } 112 113 rep(i, 1, n) { 114 scanf("%d %d", &u, &v); 115 E[u].pb(v); 116 E[v].pb(u); 117 } 118 119 // get the item in node 120 dfs(1, -1); 121 // calculate the number of valid position 122 dfs2(1, -1, INT_MIN); 123 124 printf("%d\n", ans); 125 126 #ifndef ONLINE_JUDGE 127 printf("time = %d.\n", (int)clock()); 128 #endif 129 130 return 0; 131 }