POJ 1741 Tree [点分治入门题]【分治】

——————————————————————————————————————————
Tree
Time Limit: 1000MS Memory Limit: 30000K
Total Submissions: 22808 Accepted: 7542
Description

Give a tree with n vertices,each edge has a length(positive integer less than 1001).
Define dist(u,v)=The min distance between node u and v.
Give an integer k,for every pair (u,v) of vertices is called valid if and only if dist(u,v) not exceed k.
Write a program that will count how many pairs which are valid for a given tree.
Input

The input contains several test cases. The first line of each test case contains two integers n, k. (n<=10000) The following n-1 lines each contains three integers u,v,l, which means there is an edge between node u and v of length l.
The last test case is followed by two zeros.
Output

For each test case output the answer on a single line.
Sample Input

5 4
1 2 3
1 3 1
1 4 2
3 5 1
0 0
Sample Output

8

——————————————————————————————————————————

——————————————————————————————————————————

#include <stdio.h>
#include <vector>
#include <iostream>
#include <algorithm>
#include <string.h>

using namespace std;

const int N   = 20000+7;

/*********************************/

int n,k,ans;

bool vis[N];
int d[N],f[N];

struct edge{
int to,next;
int w;
}G[N<<1];
}

/********重心 begin********/
int sz[N],dn[N],siz,zx;

void getzx(int u,int fa=0){
sz[u]=1;dn[u]=0;
to = G[i].to;
if(to == fa||vis[to]) continue;
getzx(to,u);
sz[u]+=sz[to];
dn[u]=max(dn[u],sz[to]);
}
dn[u]=max(dn[u],siz-sz[u]);
if(dn[u]<dn[zx]) zx=u;
}

/*********重心 end********/
/**
d[] 为当前节点到当前树根的距离
f[] 就是记录当前处理的子树的每个节点的d[]
*/
void getd(int u,int fa=0){
f[++f[0]] = d[u];
to=G[i].to;
if(to==fa||vis[to]) continue;
d[to]=d[u]+G[i].w;
getd(to,u);
}
}

int cal(int u,int w){
d[u]=w; f[0]=0;int sum = 0;
getd(u); sort(f+1,f+f[0]+1);
for(int l=1,r=f[0];l<r;){
if(f[l]+f[r]<=k){sum+=r-l;l++;}
else r--;
}
return sum;
}

void solve(int u){
ans+=cal(u,0);
vis[u]=1;
to=G[i].to;
if(vis[to]) continue;
ans-=cal(to,G[i].w);
siz=sz[to],zx=0;getzx(to);
solve(zx);
}
}

int main(){
while(~scanf("%d%d",&n,&k)&&(n||k)){

memset(vis,0,sizeof(vis));
dn[0]=n*10;zx=0;tot=0;

for(int i=1,u,v,w;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
}

siz = n; getzx(1);
ans = 0;solve(zx);

printf("%d\n",ans);
}
return 0;
}
07-14 27
01-28

08-02 9523
01-14 471
05-24 284
11-28 643
10-14 497
07-17 232
08-14 101
10-10 1573