点分治。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 20050 #define maxe 50050 #define inf 1000000007 using namespace std; struct edge { int v,w,nxt; }e[maxe]; int n,x,y,z,g[maxv],nume=0,root,minn,size[maxv],sum,ans=0,t[5],dis[maxv]; bool vis[maxv]; void addedge(int u,int v,int w) { e[++nume].v=v; e[nume].w=w; e[nume].nxt=g[u]; g[u]=nume; } int gcd(int x,int y) { if (x==0) return y; else return gcd(y%x,x); } void get_root(int x,int fath) { int ret=0;size[x]=1; for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if ((!vis[v]) && (v!=fath)) { get_root(v,x); size[x]+=size[v]; ret=max(ret,size[v]); } } ret=max(ret,sum-size[x]); if (ret<minn) {minn=ret;root=x;} } void get_dis(int x,int fath) { t[dis[x]%3]++; for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if ((v!=fath) && (!vis[v])) { dis[v]=dis[x]+e[i].w; get_dis(v,x); } } } int calc(int x,int fir) { t[0]=0;t[1]=0;t[2]=0;dis[x]=fir; get_dis(x,x); return t[1]*t[2]*2+t[0]*t[0]; } void work(int x) { vis[x]=true; ans+=calc(x,0); for (int i=g[x];i;i=e[i].nxt) { int v=e[i].v; if (!vis[v]) { ans-=calc(v,e[i].w); sum=size[v];root=0;minn=inf; get_root(v,v); work(root); } } } int main() { memset(vis,false,sizeof(vis)); scanf("%d",&n); for (int i=1;i<=n-1;i++) { scanf("%d%d%d",&x,&y,&z); addedge(x,y,z); addedge(y,x,z); } minn=inf;sum=n;get_root(1,1); work(root); int now=gcd(ans,n*n); printf("%d/%d\n",ans/now,n*n/now); return 0; }