版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/84892509
传送门
解析:
维护从子树内到该节点上有多少条路径模3余0,1,2就行了。
统计考虑以每个点为 的路径有多少条满足条件。
(其实这道题可以点分治)
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
cs int N=20004;
int last[N],nxt[N<<1],to[N<<1],ecnt;
int w[N<<1];
inline void addedge(int u,int v,int val){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u,w[ecnt]=val;
}
int ans;
int f[N][3];
inline void dfs(int u,int fa){
++f[u][0];
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]]){
if(v==fa)continue;
dfs(v,u);
for(int re i=0;i<3;++i)ans+=f[u][i]*f[v][(6-i-w[e])%3];
for(int re i=0;i<3;++i)f[u][i]+=f[v][(i+3-w[e])%3];
}
}
int n;
signed main(){
n=getint();
for(int re i=1;i<n;++i){
re int u=getint(),v=getint(),w=getint();
addedge(u,v,w%3);
}
dfs(1,0);
ans=ans*2+n;
re int g=__gcd(ans,n*n);
printf("%d/%d",ans/g,n*n/g);
return 0;
}