<题意概括>
给定一棵树,求树上距离为3的倍数的点对对数
<做法>
有关树上路径统计的问题当然可以想到点分治
与普通点分治一样的做法
在统计路径时使用$Ans_{i}$来储存$Length\equiv i(mod3)$的路径条数
则易知答案数为$Ans_{0}^{2}+2*Ans_{1}*Ans_{2}$$(0+0\equiv 1+2\equiv 2+1\equiv 0(mod3))$
<Code>
#include<cstdio> #include<cstring> #define Fast register #define INF 2147483647 inline int gcd(const int&x,const int&y){return y?gcd(y,x%y):x;} 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; } #define Mod(x) ((x)%3) #define Max(x,y) (x>y?x:y) int Distance[20001]; int Ans[3]; int Answer; int root; int Recent_Node; int MaxSize[20001]; int Size[20001]; bool vis[20001]; struct Edge{ int to,v;Edge*next; Edge(const int&T,const int&V,Edge*&N):to(T),v(V),next(N){} }*Front[20001]; #define AddEdge(F,T,V) Front[F]=new Edge(T,V,Front[F]) 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(!vis[o->to]&&o->to!=Fa){ 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){ ++Ans[Mod(Distance[now])]; for(Fast Edge*o=Front[now];o!=NULL;o=o->next){ if(!vis[o->to]&&o->to!=Fa){ Distance[o->to]=Mod(Distance[now]+o->v); Cal_Dis(o->to,now); } } } inline int Calculate(const int&now,const int&DisNow){ Ans[0]=Ans[1]=Ans[2]=0; Distance[now]=Mod(DisNow); Cal_Dis(now,0); return Ans[0]*Ans[0]+(Ans[1]*Ans[2]<<1); } inline void Slove(const int&now){ Answer+=Calculate(now,0);vis[now]=true; for(Fast Edge*o=Front[now];o!=NULL;o=o->next){ if(!vis[o->to]){ root=0;Recent_Node=Size[o->to]; Answer-=Calculate(o->to,o->v); FindBarycenter(o->to,now); Slove(root); } } } int main(){ Fast int N=Getint(),x,y,w; for(Fast int i=1;i<N;++i){ x=Getint(),y=Getint(),w=Getint(); AddEdge(x,y,Mod(w));AddEdge(y,x,Mod(w)); } MaxSize[root=0]=INF;Recent_Node=N; FindBarycenter(1,0);Slove(root); Fast int GCD=gcd(N*N,Answer); printf("%d/%d",Answer/GCD,N*N/GCD); return 0; }