淀粉质点分治板子
边权直接 mod 3
直接点分治统计出所有的符合条件的点对再和总方案数约分
至于约分.....gcd搞搞就好辣
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
inline int Max(int a,int b){return a>b?a:b;}
void read(int &x){
static char c=getchar();x=;
while(c<''||c>'') c=getchar();
while(''<=c&&c<='') x=x*+(c^),c=getchar();
}
#define N 20005
inline int M(int x){return x<?x:x-;}
int n,rt,sum,ans,tot,mxd[N],siz[N],dis[N],ra[N],rb[];bool vis[N];
int cnt,hd[N],nxt[N<<],ed[N],poi[N<<],val[N<<];
void adde(int x,int y,int v){
nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
ed[x]=cnt; poi[cnt]=y; val[cnt]=v;
}
void getrt(int x,int fa){
siz[x]=; mxd[x]=;
for(int i=hd[x];i;i=nxt[i]){
int to=poi[i];
if(to==fa||vis[to]) continue;
getrt(to,x);
siz[x]+=siz[to];
mxd[x]=Max(mxd[x],siz[to]);
}mxd[x]=Max(mxd[x],sum-siz[x]);
if(mxd[x]<mxd[rt]) rt=x;
}
void getdis(int x,int fa){
ra[++ra[]]=dis[x];
for(int i=hd[x];i;i=nxt[i]){
int to=poi[i];
if(to==fa||vis[to]) continue;
dis[to]=M(dis[x]+val[i]);
getdis(to,x);
}
}
void calc(int x){
rb[]=;
for(int i=hd[x];i;i=nxt[i]){
int to=poi[i];
if(vis[to]) continue;
ra[]=; dis[to]=val[i];
getdis(to,x);
for(int i=ra[];i;--i)
ans+=rb[ra[i]?-ra[i]:];
for(int i=ra[];i;--i) ++rb[ra[i]];
}rb[]=rb[]=rb[]=;
}
void solve(int x){
vis[x]=; calc(x);
for(int i=hd[x];i;i=nxt[i]){
int to=poi[i];
if(vis[to]) continue;
sum=siz[to]; rt=;
getrt(to,x); solve(rt);
}
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main(){
read(n); register int i; int q1,q2,q3;
for(i=;i<n;++i){
read(q1),read(q2),read(q3); q3%=;
adde(q1,q2,q3); adde(q2,q1,q3);
}mxd[rt=]=n+; sum=n; getrt(,); solve(rt);
ans=ans*+n; tot=n*n;
int g=gcd(ans,tot); ans/=g; tot/=g;
printf("%d/%d",ans,tot);
return ;
}