2018.12.08【BZOJ2152】聰聰可可(樹形DP)
阿新 • • 發佈:2018-12-17
傳送門
解析:
維護從子樹內到該節點上有多少條路徑模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;
}