[bzoj 1468] Tree

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1468

Tree

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 1517  Solved: 812
[Submit][Status][Discuss]

Description

给你一棵TREE,以及这棵树上边的距离.问有多少对点它们两者间的距离小于等于K

Input

N(n<=40000) 接下来n-1行边描述管道,按照题目中写的输入 接下来是k

Output

一行,有多少对点之间的距离小于等于k

Sample Input

7
1 6 13
6 3 9
3 5 7
4 1 3
2 4 20
4 7 2
10

Sample Output

5

点分治裸题,和poj上的不一样,不一样!!!

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define gc() getchar()
  6 #define max(a,b) ((a)>(b)?(a):(b))
  7 using namespace std;
  8 int read()
  9 {
 10     int rt=0,fl=1;char ch=gc();
 11     while(!isdigit(ch)){if(ch=='-')fl=-1;ch=gc();}
 12     while(isdigit(ch)){rt=rt*10+ch-'0';ch=gc();}
 13     return rt*fl;
 14 }
 15  
 16 const int MAXN = 100005;
 17  
 18 int h[MAXN],nx[MAXN<<1],to[MAXN<<1],val[MAXN<<1],cnt;
 19 int son[MAXN],f[MAXN],d[MAXN],deep[MAXN],root,sum,n,k,ans;
 20 bool vis[MAXN];
 21  
 22 void add_edge(int _u,int _v,int _c)
 23 {
 24     to[++cnt]=_v;
 25     nx[cnt]=h[_u];
 26     h[_u]=cnt;
 27     val[cnt]=_c;
 28 }
 29  
 30 void link(int _u,int _v,int _c)
 31 {
 32     add_edge(_u,_v,_c);
 33     add_edge(_v,_u,_c);
 34 }
 35  
 36 void clear()
 37 {
 38     memset(h,0,sizeof(h));
 39     memset(vis,0,sizeof(vis));
 40     cnt=0;
 41     ans = root = 0;
 42 }
 43  
 44 void getRoot(int rt,int fa)
 45 {
 46     son[rt]=1;
 47     f[rt]=0;
 48     for(int i=h[rt];i;i=nx[i])
 49     {
 50         if(to[i]==fa || vis[to[i]]==1)continue;
 51         getRoot(to[i],rt);
 52         son[rt] += son[to[i]];
 53         f[rt] = max(f[rt],son[to[i]]);
 54     }
 55     f[rt] = max(f[rt],sum - son[rt]);
 56     if(f[rt] < f[root]) root = rt;
 57 }
 58  
 59 void getDeep(int rt,int fa)
 60 {
 61     deep[++deep[0]] = d[rt];
 62     for(int i=h[rt];i;i=nx[i])
 63     {
 64         if(to[i]==fa || vis[to[i]]==1)continue;
 65         d[to[i]] = d[rt] + val[i];
 66         getDeep(to[i],rt);
 67     }
 68 }
 69  
 70 int cal(int x,int now)
 71 {
 72     d[x] = now;
 73     deep[0] = 0;
 74     getDeep(x,0);
 75     sort(deep+1,deep+deep[0]+1);
 76     int t = 0,l,r;
 77     for(l=1,r=deep[0];l<r;)
 78     {
 79         if(deep[l] + deep[r] <= k)
 80         {
 81             t+=r-l;
 82             l++;
 83         }
 84         else r--;
 85     }
 86     return t;
 87 }
 88 void work(int rt)
 89 {
 90     ans += cal(rt,0);
 91     vis[rt] = 1;
 92     for(int i=h[rt];i;i=nx[i])
 93     {
 94         if(vis[to[i]]==1) continue;
 95         ans -= cal(to[i],val[i]);
 96         sum = son[to[i]];
 97         root = 0;
 98         getRoot(to[i],root);
 99         work(root);
100     }
101 }
102 int main()
103 {
104     n=read();
105     for(int i=1;i<n;i++)
106     {
107         int a,b,c;
108         a=read();
109         b=read();
110         c=read();
111         link(a,b,c);
112         }
113     k=read();
114         sum = n;
115         f[0] = 0x3f3f3f3f;
116         getRoot(1,0);
117         work(root);
118         printf("%d\n",ans);
119     return 0;
120 }

 

posted @ 2017-05-27 21:08  986yg  阅读(158)  评论(0编辑  收藏  举报