【BZOJ 2152】聪聪可可 点分治

来源:互联网 发布:pc手机微信三合一源码 编辑:程序博客网 时间:2024/05/01 11:46

直接分治,然后dis对3取模,有且只有取模后为(1,2)或者(0,0)对答案有贡献加起来就好了

#include<cstdio>#include<cstring>#include<iostream>#define maxn 20020using namespace std;int s[maxn],rt,size,f[maxn],n,m,dis[maxn],head[maxn],tot=1,vis[maxn],ans;int t[3];struct edge{int v,next,w;}e[maxn*2];void adde(int a,int b,int c){e[tot].v=b,e[tot].w=c,e[tot].next=head[a];head[a]=tot++;}int gcd(int a,int b){return b==0?a:gcd(b,a%b);}void getrt(int u,int fa){f[u]=0;s[u]=1;for(int v,i=head[u];i;i=e[i].next){if(vis[v=e[i].v]||v==fa)continue;getrt(v,u);s[u]+=s[v];f[u]=max(f[u],s[v]);}f[u]=max(f[u],size-f[u]);if(f[u]<f[rt])rt=u;}void dfs(int u,int fa){t[dis[u]]++;for(int i=head[u],v;i;i=e[i].next){if(vis[v=e[i].v]||v==fa)continue;dis[v]=(dis[u]+e[i].w)%3;dfs(v,u);}}int calc(int u,int h){dis[u]=h;t[1]=t[2]=t[0]=0;dfs(u,u);return t[1]*t[2]*2+t[0]*t[0];}void solve(int u){vis[u]=1;ans+=calc(u,0);for(int v,i=head[u];i;i=e[i].next){if(vis[v=e[i].v])continue;ans-=calc(v,e[i].w);f[rt=0]=size=s[v];getrt(v,u);solve(rt);}}int main(){scanf("%d",&n);for(int a,b,c,i=1;i<n;i++){scanf("%d%d%d",&a,&b,&c);c%=3;adde(a,b,c),adde(b,a,c);}f[rt=0]=size=n;getrt(1,1);solve(rt);int g=gcd(ans,n*n);printf("%d/%d",ans/g,n*n/g);return 0;}


0 0
原创粉丝点击