数据结构(树,点分治):POJ 1741 Tree

 

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
  点分治模板……
 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 using namespace std;
 6 const int maxn=10010;
 7 int cnt,n,k,N;
 8 bool vis[maxn];
 9 int fir[maxn],to[maxn<<1],nxt[maxn<<1],val[maxn<<1];
10 void addedge(int a,int b,int v){
11     nxt[++cnt]=fir[a];fir[a]=cnt;val[cnt]=v;to[cnt]=b;
12 }
13 
14 int rt,sz[maxn],son[maxn];
15 int st[maxn],tot,dis[maxn];
16 void Get_RT(int x,int fa){
17     sz[x]=1;son[x]=0;
18     for(int i=fir[x];i;i=nxt[i])
19         if(to[i]!=fa&&!vis[to[i]]){
20             Get_RT(to[i],x);
21             sz[x]+=sz[to[i]];
22             son[x]=max(sz[to[i]],son[x]);
23         }
24     son[x]=max(son[x],N-sz[x]);    
25     if(!rt||son[rt]>son[x])rt=x;    
26 }
27 
28 void DFS(int x,int fa){
29     st[++tot]=dis[x];
30     for(int i=fir[x];i;i=nxt[i])
31         if(to[i]!=fa&&!vis[to[i]]){
32             dis[to[i]]=dis[x]+val[i];
33             DFS(to[i],x);
34         }
35 }
36 
37 int Calc(int x,int d){
38     int ret=0;tot=0;
39     dis[x]=d;DFS(x,0);
40     sort(st+1,st+tot+1);
41     int l=1,r=tot;
42     while(l<r){
43         if(st[l]+st[r]>k)r-=1;
44         else {ret+=r-l;l+=1;}
45     }
46     return ret;
47 }
48 
49 int Solve(int x){
50     vis[x]=true;
51     int ret=Calc(x,0);
52     for(int i=fir[x];i;i=nxt[i])
53         if(!vis[to[i]]){
54             ret-=Calc(to[i],val[i]);
55             N=sz[to[i]];rt=0;
56             Get_RT(to[i],0);
57             ret+=Solve(rt);
58         }
59     return ret;    
60 }
61 
62 int main(){
63     while(true){
64         scanf("%d%d",&n,&k);
65         if(!n&&!k)break;cnt=0;N=n;
66         memset(vis,0,sizeof(vis));
67         memset(fir,0,sizeof(fir));
68         for(int i=1,a,b,v;i<n;i++){
69             scanf("%d%d%d",&a,&b,&v);
70             addedge(a,b,v);addedge(b,a,v);
71         }
72         Get_RT(1,0);
73         printf("%d\n",Solve(rt));
74     }
75     return 0;
76 }

 

posted @ 2016-06-17 21:59  TenderRun  阅读(175)  评论(0编辑  收藏  举报