ポータルは、
点線のガバナンスの実践に手をやっています。
主に長さの木追求\(3 \) 、もちろん、より便利な点線のルールの複数のパスの数を
記録パスの長さ\(\%3 \)番号の後に番号を、あなたは現在のパスを見つけることによって、およびすることができます作るこれは\(3 \)のパス何倍
、それは部分的な順序があるので、そう答え、\(\タイムズ2 \) 、プラス当然の\(I-> I \)プログラム全体の\(N- \)バー。
#include <bits/stdc++.h>
using namespace std;
const int MAXN=2e4+10;
int n;
int head[MAXN],to[MAXN*2],nxt[MAXN*2],val[MAXN*2],tot;
int siz[MAXN],maxp[MAXN],sum,rt,dead[MAXN];
int path[4],cnt,dis[MAXN],ans;
void add(int u,int v,int w){
to[++tot]=v;nxt[tot]=head[u];val[tot]=w;head[u]=tot;
}
void getrt(int u,int fa){
siz[u]=1;maxp[u]=0;
for(int i=head[u];i;i=nxt[i]){
if(to[i]==fa||dead[to[i]]) continue;
getrt(to[i],u);
siz[u]+=siz[to[i]];
maxp[u]=max(maxp[u],siz[to[i]]);
}
maxp[u]=max(maxp[u],sum-siz[u]);
if(maxp[u]<maxp[rt]) rt=u;
}
void getdis(int u,int fa,int w){
dis[++cnt]=w;
for(int i=head[u];i;i=nxt[i]){
if(to[i]==fa||dead[to[i]]) continue;
getdis(to[i],u,w+val[i]);
}
}
void calc(int u){
path[0]=1;
for(int i=head[u];i;i=nxt[i]){
if(dead[to[i]]) continue;
cnt=0;
getdis(to[i],u,val[i]);
for(int j=1;j<=cnt;j++)
if(dis[j]%3==0) ans+=path[0];
else ans+=path[3-dis[j]%3];
for(int j=1;j<=cnt;j++) path[dis[j]%3]++;
}
memset(path,0,sizeof(path));
}
void divide(int u){
dead[u]=1;
calc(u);
for(int i=head[u];i;i=nxt[i]){
if(dead[to[i]]) continue;
maxp[rt=0]=sum=siz[to[i]];
getrt(to[i],0);
getrt(rt,0);
divide(rt);
}
}
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int main(){
#ifndef ONLINE_JUDGE
freopen("data.in","r",stdin);
freopen("data.out","w",stdout);
#endif
scanf("%d",&n);
for(int i=1,u,v,w;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
maxp[0]=sum=n;
getrt(1,0);
getrt(rt,0);
divide(rt);
ans=ans*2+n;
int a=ans,b=n*n,d=gcd(a,b);
printf("%d/%d\n",a/d,b/d);
return 0;
}