【BZOJ 2152】 聪聪可可
为了做那个列表 扯到这么远........
不能乱立Flag啊!!!
#include <cstdio>
#include <iostream>
#define MAXN 400000
using namespace std;
int num[MAXN],g[MAXN],nnext[MAXN],cost[MAXN],tot;
int n,root,size[MAXN],f[MAXN],sum;
int ans=0;
bool b[MAXN];
void Find_Root(int x,int fa)
{
f[x]=0;
size[x]=1;
for(int i=g[x];i;i=nnext[i])
if(num[i]!=fa&&!b[num[i]])
{
Find_Root(num[i],x);
f[x]=max(f[x],size[num[i]]);
size[x]+=size[num[i]];
}
f[x]=max(f[x],sum-f[x]);
if(f[x]<f[root]) root=x;
}
int T[3];
void Dfs(int x,int fa,int k)
{
T[k]++;
for(int i=g[x];i;i=nnext[i])
if(num[i]!=fa&&!b[num[i]])
Dfs(num[i],x,(k+cost[i])%3);
}
void Do(int x)
{
b[x]=true;
int N0=0,N1=0,N2=0;
for(int i=g[x];i;i=nnext[i])
if(!b[num[i]])
{
T[0]=T[1]=T[2]=0;
Dfs(num[i],-1,cost[i]);
ans+=T[0]+T[0]*N0+T[1]*N2+T[2]*N1;
N0+=T[0],N1+=T[1],N2+=T[2];
sum=size[num[i]];
root=0;
Find_Root(num[i],-1);
Do(root);
}
// cout<<x<<' '<<N0<<' '<<N1<<' '<<N2<<endl;
}
int Gcd(int x,int y)
{
if(y==0) return x;
return Gcd(y,x%y);
}
int main()
{
cin>>n; if(n==0) {cout<<"0/1";return 0;}
for(int i=1;i<n;i++)
{
int x,y,z;
scanf("%d %d %d",&x,&y,&z);
tot++;nnext[tot]=g[x];g[x]=tot;num[tot]=y;cost[tot]=z%3;
tot++;nnext[tot]=g[y];g[y]=tot;num[tot]=x;cost[tot]=z%3;
}
root=0;
f[0]=n+1;
sum=n;
Find_Root(1,-1);
Do(root);
ans=ans*2+n;
n=n*n;
int t=Gcd(ans,n);
cout<<ans/t<<'/'<<n/t;
return 0;
}