传送门biu~
这道题才是树分治裸题。。
#include<bits/stdc++.h>
using namespace std;
int n,center,ans;
bool b[20005];
int f[3],g[3];
int head[20005],nex[40005],to[40005],val[40005],tp;
inline void add(int x,int y,int z){
nex[++tp]=head[x];
head[x]=tp;
to[tp]=y;
val[tp]=z;
}
int siz[20005],fa[20005];
void get_tree_center(int x,int father,int tot){
fa[x]=father;
siz[x]=1;
bool flag=true;
for(int i=head[x];i;i=nex[i]){
if(to[i]==father || b[to[i]]) continue;
get_tree_center(to[i],x,tot);
if(siz[to[i]]>tot/2) flag=false;
siz[x]+=siz[to[i]];
}
if(tot-siz[x]>tot/2) flag=false;
if(flag) center=x;
}
void dfs(int x,int father,int len){
++f[len];
for(int i=head[x];i;i=nex[i]){
if(to[i]==father || b[to[i]]) continue;
dfs(to[i],x,(len+val[i])%3);
}
}
void tree_divide(int x){
int tot=siz[x];
get_tree_center(x,0,tot);
x=center;
if(fa[x]) siz[fa[x]]=tot-siz[x];
g[0]=1;
for(int i=head[x];i;i=nex[i]){
if(b[to[i]]) continue;
dfs(to[i],x,val[i]);
ans+=f[0]*g[0]+f[1]*g[2]+f[2]*g[1];
for(int j=0;j<=2;++j) g[j]+=f[j],f[j]=0;
}
for(int i=0;i<=2;++i) g[i]=0;
b[x]=1;
for(int i=head[x];i;i=nex[i]){
if(b[to[i]]) continue;
tree_divide(to[i]);
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;++i){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
z%=3;
add(x,y,z);
add(y,x,z);
}
siz[1]=n;
tree_divide(1);
ans=ans*2+n;
int p=n*n;
int G=__gcd(ans,p);
printf("%d/%d",ans/G,p/G);
return 0;
}