求出子树的重心后求出它每个子节点的距离,排序后就可以统计距离小于等于K的点对的个数了,但是会在同一子树内重复,然后在每个子树里面减去小于等于K的点对个数就可以了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <algorithm> 5 using namespace std; 6 const int Maxn=10010; 7 const int Inf=0x3f3f3f3f; 8 int n,k,Root,u,v,w,Sum,Size[Maxn],Q[Maxn],F[Maxn],d[Maxn],cnt,head[Maxn],vis[Maxn],Top,Ans; 9 struct EDGE{int to,next,w;}edge[Maxn<<2]; 10 inline int Max(int x,int y) {return x>y?x:y;} 11 inline void Add(int u,int v,int w) {edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt++;} 12 void Get_Root(int u,int fa) 13 { 14 Size[u]=1; F[u]=0; 15 for (int i=head[u];i!=-1;i=edge[i].next) 16 { 17 int v=edge[i].to; 18 if (v==fa || vis[v]) continue; 19 Get_Root(v,u); 20 Size[u]+=Size[v]; 21 F[u]=Max(F[u],Size[v]); 22 } 23 F[u]=Max(F[u],Sum-Size[u]); 24 if (F[u]<F[Root]) Root=u; 25 } 26 void Get_Deep(int u,int fa) 27 { 28 Q[++Top]=d[u]; 29 for (int i=head[u];i!=-1;i=edge[i].next) 30 { 31 int v=edge[i].to; 32 if (v==fa || vis[v]) continue; 33 d[v]=d[u]+edge[i].w; 34 Get_Deep(v,u); 35 } 36 } 37 int Calc(int u,int value) 38 { 39 d[u]=value; Top=0; Get_Deep(u,0); 40 sort(Q+1,Q+Top+1); 41 int l=1,r=Top,Res=0; 42 while (l<=r) 43 { 44 if (Q[l]+Q[r]<=k) 45 Res+=r-l,l++; else r--; 46 } 47 return Res; 48 } 49 void Work(int u) 50 { 51 Ans+=Calc(u,0); vis[u]=true; 52 for (int i=head[u];i!=-1;i=edge[i].next) 53 { 54 int v=edge[i].to; 55 if (vis[v]) continue; 56 Ans-=Calc(v,edge[i].w); 57 Sum=Size[v]; Root=0; 58 Get_Root(v,u); 59 Work(Root); 60 } 61 } 62 int main() 63 { 64 while (scanf("%d%d",&n,&k)!=EOF) 65 { 66 if (n==0 && k==0) break; 67 Ans=0; cnt=0; memset(head,-1,sizeof(head)); 68 for (int i=1;i<n;i++) 69 { 70 scanf("%d%d%d",&u,&v,&w); 71 Add(u,v,w),Add(v,u,w); 72 } 73 memset(vis,false,sizeof(vis)); 74 Sum=n; F[0]=Inf; 75 Get_Root(1,0); 76 Work(Root); 77 printf("%d\n",Ans); 78 } 79 return 0; 80 }