1. 程式人生 > >【poj1741 Tree】

【poj1741 Tree】

sin write col return else pairs ast sam min

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

題解:

  第一次寫點分治感覺還好吧,對於一個子樹先預處理出sz,然後求出樹的重心,然後再分治下去。

  計算答案時會算重,比如兩個點都是當前重心的子節點,所以要容斥刪去。(記得每次尋找重心要初始化)

 

 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using
namespace std; 7 struct nd{ 8 int to,next,v; 9 } e[20005]; 10 int head[10005],dep[10005],d[10005],mx[10005],sz[10005]; 11 bool vis[10005]; 12 int sum,ans,rt; 13 int n,k,cnt; 14 inline void insert(int u,int v,int w){ 15 e[++cnt].next=head[u]; 16 head[u]=cnt; 17 e[cnt].to=v; 18 e[cnt].v=w; 19 } 20 inline void findG(int now,int fa){ 21 mx[now]=0; 22 for(int i=head[now];i;i=e[i].next){ 23 if(e[i].to==fa || vis[e[i].to]) continue; 24 findG(e[i].to,now); 25 mx[now]=max(mx[now],sz[e[i].to]); 26 } 27 mx[now]=max(mx[now],sum-sz[now]); 28 if(mx[now]<mx[rt]) rt=now; 29 } 30 inline void findS(int now,int fa){ 31 sz[now]=1; 32 for(int i=head[now];i;i=e[i].next){ 33 if(vis[e[i].to] || e[i].to==fa) continue; 34 findS(e[i].to,now); 35 sz[now]+=sz[e[i].to]; 36 } 37 } 38 inline void findD(int now,int fa){ 39 dep[++dep[0]]=d[now]; 40 for(int i=head[now];i;i=e[i].next){ 41 if(vis[e[i].to] || e[i].to==fa) continue; 42 d[e[i].to]=d[now]+e[i].v; 43 findD(e[i].to,now); 44 } 45 } 46 inline int cal(int now,int x){ 47 d[now]=x;dep[0]=0; 48 findD(now,-1); 49 sort(dep+1,dep+dep[0]+1); 50 int num=0,l,r; 51 for(int l=1,r=dep[0];l<r;){ 52 if(dep[l]+dep[r]<=k){ 53 num+=r-l;l++; 54 } 55 else r--; 56 } 57 return num; 58 } 59 inline void work(int x) 60 { 61 ans+=cal(x,0); 62 vis[x]=1; 63 for(int i=head[x];i;i=e[i].next){ 64 if(vis[e[i].to]) continue; 65 ans-=cal(e[i].to,e[i].v); 66 findS(e[i].to,x); 67 sum=sz[e[i].to]; 68 rt=0; 69 findG(e[i].to,x); 70 work(rt); 71 } 72 } 73 int main(){ 74 int u,v,w; 75 while(1){ 76 ans=0,cnt=0; 77 memset(vis,0,sizeof(vis)); 78 memset(head,0,sizeof(head)); 79 scanf("%d%d",&n,&k); 80 if(!n) return 0; 81 for(int i=1;i<n;i++){ 82 scanf("%d%d%d",&u,&v,&w); 83 insert(u,v,w); 84 insert(v,u,w); 85 } 86 rt=0; 87 mx[rt]=1e9+7; 88 findS(1,-1); 89 sum=sz[1]; 90 findG(1,-1); 91 work(rt); 92 printf("%d\n",ans); 93 } 94 }

【poj1741 Tree】