典型的点分治。。。可惜有一部不会做。。。

如何找出某个点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 }
View Code

 

By Xs酱~ 转载请说明 博客地址:http://www.cnblogs.com/rausen
posted on 2014-12-20 20:25  Xs酱~  阅读(228)  评论(0编辑  收藏  举报