典型的点分治。。。可惜有一部不会做。。。
如何找出某个点p的子树中过p的链的数量?、、、(语文不好不要打我)
于是Orz cxjyxx,可以先求出所有的答案再减掉不是的答案(说了语文不好不要打我了啊>_<)
其实貌似可以用点分树来写。。。的说?
1 /************************************************************** 2 Problem: 1468 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:756 ms 7 Memory:2528 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 const int N = 40005; 15 16 struct edge { 17 int next, to, v; 18 edge() {} 19 edge(int _n, int _t, int _v) : next(_n), to(_t), v(_v) {} 20 } e[N << 1]; 21 22 int first[N], tot; 23 24 struct tree_node { 25 int sz, dep; 26 bool vis; 27 } tr[N]; 28 29 int n, k, ans; 30 int dep[N], cnt_dep; 31 int Root, Maxsz; 32 33 inline int read() { 34 int x = 0; 35 char ch = getchar(); 36 while (ch < '0' || '9' < ch) 37 ch = getchar(); 38 while ('0' <= ch && ch <= '9') { 39 x = x * 10 + ch - '0'; 40 ch = getchar(); 41 } 42 return x; 43 } 44 45 void Add_Edges(int x, int y, int z) { 46 e[++tot] = edge(first[x], y, z), first[x] = tot; 47 e[++tot] = edge(first[y], x, z), first[y] = tot; 48 } 49 50 void dfs(int p, int fa, int sz) { 51 int x, y, maxsz = 0; 52 tr[p].sz = 1; 53 for (x = first[p]; x; x = e[x].next) 54 if ((y = e[x].to) != fa && !tr[y].vis) { 55 dfs(y, p, sz); 56 tr[p].sz += tr[y].sz; 57 maxsz = max(maxsz, tr[y].sz); 58 } 59 maxsz = max(maxsz, sz - tr[p].sz); 60 if (maxsz < Maxsz) 61 Root = p, Maxsz = maxsz; 62 } 63 64 int get_root(int p, int sz) { 65 Maxsz = N << 1; 66 dfs(p, 0, sz); 67 return Root; 68 } 69 70 void get_dep(int p, int fa) { 71 int x, y; 72 dep[++cnt_dep] = tr[p].dep; 73 for (x = first[p]; x; x = e[x].next) 74 if ((y = e[x].to) != fa && !tr[y].vis) { 75 tr[y].dep = tr[p].dep + e[x].v; 76 get_dep(y, p); 77 } 78 } 79 80 int cal(int p, int now) { 81 tr[p].dep = now, cnt_dep = 0; 82 get_dep(p, 0); 83 sort(dep + 1, dep + cnt_dep + 1); 84 int res = 0, l, r; 85 for (l = 1, r = cnt_dep; l < r; ) 86 if (dep[l] + dep[r] <= k) 87 res += r - l, ++l; 88 else --r; 89 return res; 90 } 91 92 void work(int p, int sz) { 93 int root = get_root(p, sz), x, y; 94 ans += cal(root, 0); 95 tr[root].vis = 1; 96 for (x = first[root]; x; x = e[x].next) 97 if (!tr[y = e[x].to].vis) { 98 ans -= cal(y, e[x].v); 99 work(y, tr[p].sz); 100 } 101 } 102 103 int main() { 104 int i, x, y, z; 105 n = read(); 106 for (i = 1; i < n; ++i) { 107 x = read(), y = read(), z = read(); 108 Add_Edges(x, y, z); 109 } 110 k = read(); 111 work(1, n); 112 printf("%d\n", ans); 113 return 0; 114 }
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen