<题意概括>
给定一棵树,求有多少对满足两两距离不超过k的点对(u,v)
<做法>
典型的点分治题目
找出当前树的重心
计算该顶点到其子树中每个顶点的路径长度
使用双指针法统计满足条件的路径条数并减去那些在同一棵子树中的路径
删除该顶点并递归处理每一棵子树
<Code>
#include<cstdio> #include<cstring> #include<algorithm> #define Fast register #define INF 2147483647 inline int Max(const int&x,const int&y){return x>y?x:y;} inline char Getchar(){ static char BUF[16384],*S=BUF,*T=BUF; return(S==T)&&(T=(S=BUF)+fread(BUF,1,16384,stdin),S==T)?EOF:*S++; } inline int Getint(){ Fast int s=0;Fast char c=Getchar(); while(c<48||c>57)c=Getchar(); while(c>47&&c<58)s=s*10+c-48,c=Getchar(); return s; } struct Edge{ int to,v;Edge*next; Edge(const int&T,const int&V,Edge*&N):to(T),v(V),next(N){} }*Front[40001]; #define AddEdge(x,y,z) Front[x]=new Edge(y,z,Front[x]) int root; int Size[40001]; int MaxSize[40001]; int Recent_Node; bool vis[40001]; int Distance[40001]; int Dis[40001]; int Cnt_Dis; int N,DisLimit; int Ans; inline void FindBarycenter(const int&now,const int&Fa){ Size[now]=1;MaxSize[now]=0; for(Fast Edge*o=Front[now];o!=NULL;o=o->next){ if(o->to!=Fa&&!vis[o->to]){ FindBarycenter(o->to,now); Size[now]+=Size[o->to]; MaxSize[now]=Max(MaxSize[now],Size[o->to]); } } MaxSize[now]=Max(MaxSize[now],Recent_Node-Size[now]); if(MaxSize[now]<MaxSize[root])root=now; } inline void Cal_Dis(const int&now,const int&Fa){ Dis[++Cnt_Dis]=Distance[now]; for(Fast Edge*o=Front[now];o!=NULL;o=o->next){ if(o->to!=Fa&&!vis[o->to]){ Distance[o->to]=Distance[now]+o->v; Cal_Dis(o->to,now); } } } inline int Calculate(const int&now,const int&DisNow){ Distance[now]=DisNow,Cnt_Dis=0; Cal_Dis(now,0); std::sort(Dis+1,Dis+Cnt_Dis+1); Fast int L=1,R=Cnt_Dis,Num=0; while(L<R)Dis[L]+Dis[R]<=DisLimit?Num+=R-L,++L:--R; return Num; } inline void Slove(const int&now){ Ans+=Calculate(now,0),vis[now]=true; for(Fast Edge*o=Front[now];o!=NULL;o=o->next){ if(!vis[o->to]){ Ans-=Calculate(o->to,o->v); root=0; Recent_Node=Size[o->to]; FindBarycenter(o->to,now); Slove(root); } } } int main(){ N=Getint(); for(Fast int i=1;i<N;++i){ Fast int u=Getint(),v=Getint(),l=Getint(); AddEdge(u,v,l);AddEdge(v,u,l); } DisLimit=Getint(); MaxSize[root=0]=INF; Recent_Node=N; FindBarycenter(1,0); Slove(root); printf("%d\n",Ans); return 0; }
#include<cstdio> #include<cstring> #include<algorithm> #define Fast register #define INF 2147483647 inline int Max(const int&x,const int&y){return x>y?x:y;} inline char Getchar(){ static char BUF[16384],*S=BUF,*T=BUF; return(S==T)&&(T=(S=BUF)+fread(BUF,1,16384,stdin),S==T)?EOF:*S++; } inline int Getint(){ Fast int s=0;Fast char c=Getchar(); while(c<48||c>57)c=Getchar(); while(c>47&&c<58)s=s*10+c-48,c=Getchar(); return s; } struct Edge{ int to,v;Edge*next; Edge(const int&T,const int&V,Edge*&N):to(T),v(V),next(N){} }*Front[10001]; #define AddEdge(x,y,z) Front[x]=new Edge(y,z,Front[x]) int root; int Size[10001]; int MaxSize[10001]; int Recent_Node; bool vis[10001]; int Distance[10001]; int Dis[10001]; int Cnt_Dis; int N,DisLimit; int Ans; inline void FindBarycenter(const int&now,const int&Fa){ Size[now]=1;MaxSize[now]=0; for(Fast Edge*o=Front[now];o!=NULL;o=o->next){ if(o->to!=Fa&&!vis[o->to]){ FindBarycenter(o->to,now); Size[now]+=Size[o->to]; MaxSize[now]=Max(MaxSize[now],Size[o->to]); } } MaxSize[now]=Max(MaxSize[now],Recent_Node-Size[now]); if(MaxSize[now]<MaxSize[root])root=now; } inline void Cal_Dis(const int&now,const int&Fa){ Dis[++Cnt_Dis]=Distance[now]; for(Fast Edge*o=Front[now];o!=NULL;o=o->next){ if(o->to!=Fa&&!vis[o->to]){ Distance[o->to]=Distance[now]+o->v; Cal_Dis(o->to,now); } } } inline int Calculate(const int&now,const int&DisNow){ Distance[now]=DisNow,Cnt_Dis=0; Cal_Dis(now,0); std::sort(Dis+1,Dis+Cnt_Dis+1); Fast int L=1,R=Cnt_Dis,Num=0; while(L<R)Dis[L]+Dis[R]<=DisLimit?Num+=R-L,++L:--R; return Num; } inline void Slove(const int&now){ Ans+=Calculate(now,0);vis[now]=true; for(Fast Edge*o=Front[now];o!=NULL;o=o->next){ if(!vis[o->to]){ Ans-=Calculate(o->to,o->v); root=0; Recent_Node=Size[o->to]; FindBarycenter(o->to,now); Slove(root); } } } int main(){ while(N=Getint(),DisLimit=Getint(),N||DisLimit){ Recent_Node=N; memset(Front,NULL,sizeof Front); memset(vis,false,sizeof vis); for(Fast int i=1;i<N;++i){ Fast int u=Getint(),v=Getint(),l=Getint(); AddEdge(u,v,l);AddEdge(v,u,l); } MaxSize[Ans=root=0]=INF; FindBarycenter(1,0); Slove(root); printf("%d\n",Ans); } return 0; }