• 点分治


    对于无根树,指定重心为根,考虑分别统计经过根的和不经过根的,在分别统计子树

     1 const int Mn = 10000 + 10 , Me = 2 * 10000 + 10;
     2 int hd[Mn],nxt[Me],to[Me],w[Me],cnt;
     3 int size[Mn],dis[Mn],g[Mn],tot;
     4 bool vis[Mn];
     5 int n,k;
     6 inline void add(int x, int y, int z)
     7 {
     8     to[cnt] = y;
     9     w[cnt] = z;
    10     nxt[cnt] = hd[x];
    11     hd[x] = cnt++;
    12 }
    13 inline void dfs_dis(int x,int dist,int p)
    14 {
    15     dis[++tot] = dist;
    16     for(int i = hd[x]; ~i; i = nxt[i])
    17     if(!vis[to[i]] && i != p)
    18     dfs_dis(to[i],dist+w[i],i^1);
    19 }
    20 inline int find_root(int x,int p,int root)
    21 {
    22     int minx = n;
    23     int ret(0);
    24     for(int i = hd[x];~i; i = nxt[i])
    25     if(!vis[to[i]] && i != p)
    26     {
    27         int tmp = find_root(to[i],i^1,root);
    28         if(g[tmp] < minx) 
    29         ret = tmp,minx = g[tmp];
    30     }
    31     g[x] = max(g[x],size[root]-size[x]);
    32     if(g[x] < minx) ret = x;
    33     return ret;
    34 }
    35 inline void dfs_root(int x,int p)
    36 {
    37     size[x] = 1;
    38     g[x] = 0;
    39     for(int i = hd[x];~i; i = nxt[i])
    40     if(!vis[to[i]] && i != p)
    41     {
    42         dfs_root(to[i],i^1);
    43         size[x] += size[to[i]];
    44         g[x] = max(g[x],size[to[i]]);
    45     }
    46 }
    47 inline int get_root(int x)
    48 {
    49     dfs_root(x,-1);
    50     return find_root(x,-1,x);
    51 }
    52 inline int calc(int x, int y)
    53 {
    54     tot = 0;
    55     dfs_dis(x,y,-1);
    56     sort(dis+1,dis+tot+1);
    57     int j = tot;
    58     int res(0);
    59     for(int i = 1; i < j; i++)
    60     {
    61         while(dis[i] + dis[j] > k && i < j) j--;
    62         res += j-i;
    63     }
    64     return res;
    65 }
    66 inline int dfs(int x)
    67 {
    68     int root = get_root(x);
    69     vis[root] = true;
    70     int res(0);
    71     res += calc(root,0);
    72     for(int i = hd[root]; ~i; i = nxt[i])
    73     if(!vis[to[i]])
    74     {
    75         res -= calc(to[i],w[i]);
    76         res += dfs(to[i]);
    77     }
    78     return res;
    79 }
    80 int main()
    81 {
    82     while(scanf("%d%d",&n,&k),n+k)
    83     {
    84         cnt = 0;
    85         memset(hd,-1,sizeof hd);
    86         memset(vis,false,sizeof vis);
    87         for(int i = 1; i < n; i++)
    88         {
    89             int x,y,z;
    90             scanf("%d%d%d",&x,&y,&z);
    91             add(x,y,z);
    92             add(y,x,z);
    93         }
    94         printf("%d
    ",dfs(1));
    95     }
    96 }
  • 相关阅读:
    关于范型
    c#.net实体类序列化方法  为什么要序列化
    游标示例
    干掉switch语句
    java面向对象总结(一)
    Java泛型简明教程(转)
    java 成员变量、局部变量、静态变量
    Java 集合类图(转)
    java泛型(擦除)
    java垃圾回收
  • 原文地址:https://www.cnblogs.com/universeplayer/p/10658744.html
Copyright © 2020-2023  润新知