[bzoj2152]聪聪可可
树分治。
边的话存的时候存成mod 3后的边就行,然后其他的就是套模板了。(数组开太大会被T的。。。)

1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cmath> 7 using namespace std; 8 9 const int N=50000; 10 int h[20010],r[40010],to[40010],w[40010],d[20010],sz[20010],f[20010],root,sum,tot,n,ans,t[5]; 11 bool v[20010]; 12 int gcd(int a,int b){return b?gcd(b,a%b):a;} 13 void ins(int u,int v,int z){ 14 to[tot]=v; 15 w[tot]=z%3; 16 r[tot]=h[u]; 17 h[u]=tot++; 18 } 19 void getRoot(int x,int fa){ 20 sz[x]=1;f[x]=0; 21 for(int i=h[x];i!=-1;i=r[i]){ 22 if(!v[to[i]]&&to[i]!=fa){ 23 getRoot(to[i],x); 24 sz[x]+=sz[to[i]]; 25 f[x]=max(f[x],sz[to[i]]); 26 } 27 } 28 f[x]=max(f[x],sum-sz[x]); 29 if(f[x]<f[root])root=x; 30 } 31 void getDeep(int x,int fa){ 32 t[d[x]]++; 33 for(int i=h[x];i!=-1;i=r[i]){ 34 if(!v[to[i]]&&to[i]!=fa){ 35 d[to[i]]=(d[x]+w[i])%3; 36 getDeep(to[i],x); 37 } 38 } 39 } 40 int calc(int x,int val){ 41 d[x]=val;t[0]=t[1]=t[2]=0; 42 getDeep(x,0); 43 return t[0]*t[0]+t[1]*t[2]*2; 44 } 45 void work(int x){ 46 ans+=calc(x,0); 47 v[x]=1; 48 for(int i=h[x];i!=-1;i=r[i]){ 49 if(!v[to[i]]){ 50 ans-=calc(to[i],w[i]); 51 root=0; 52 sum=sz[to[i]]; 53 getRoot(to[i],0); 54 work(root); 55 } 56 } 57 } 58 inline int read(){ 59 static int f,ret; 60 static char c; 61 ret=0;f=1; 62 c=getchar(); 63 while(c>'9'||c<'0'){ 64 if(c=='-')f=-1; 65 c=getchar(); 66 } 67 while(c>='0'&&c<='9')ret=(ret<<1)+(ret<<3)+c-'0',c=getchar(); 68 return ret*f; 69 } 70 int main(){ 71 n=read(); 72 memset(h,-1,sizeof(h)); 73 for(int i=1,u,v,z;i<n;i++){ 74 u=read(); 75 v=read(); 76 z=read(); 77 ins(u,v,z);ins(v,u,z); 78 } 79 f[0]=sum=n; 80 getRoot(1,0); 81 work(root); 82 int g=gcd(ans,n*n); 83 printf("%d/%d\n",ans/g,n*n/g); 84 }