欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

bzoj 2152: 聪聪可可【点分治】

程序员文章站 2022-05-08 18:25:44
...

裸的点分治,运算在模3下进行然后统计答案的时候统计余1的*余2的*2+余0的^2

#include<iostream>
#include<cstdio>
using namespace std;
const int N=20005;
int n,h[N],cnt,ans,rt,sum,si[N],hs[N],de[N],t[5];
bool v[N];
struct qwe
{
    int to,ne,va;
}e[N<<1];
int read()
{
    int r=0,f=1;
    char p=getchar();
    while(p>'9'||p<'0')
    {
        if(p=='-')
            f=-1;
        p=getchar();
    }
    while(p>='0'&&p<='9')
    {
        r=r*10+p-48;
        p=getchar();
    }
    return r*f;
}
void add(int u,int v,int w)
{
    cnt++;
    e[cnt].ne=h[u];
    e[cnt].to=v;
    e[cnt].va=w;
    h[u]=cnt;
}
int gcd(int a,int b)
{
    return b==0?a:gcd(b,a%b);
}
void getrt(int u,int fa)
{
    si[u]=1;hs[u]=0;
    for(int i=h[u];i;i=e[i].ne)
        if(!v[e[i].to]&&e[i].to!=fa)
        {
            getrt(e[i].to,u);
            si[u]+=si[e[i].to];
            hs[u]=max(hs[u],si[e[i].to]);
        }
    hs[u]=max(hs[u],sum-si[u]);
    if(hs[u]<hs[rt])
        rt=u;
}
void gtde(int u,int fa)
{
    t[de[u]]++;
    for(int i=h[u];i;i=e[i].ne)
        if(!v[e[i].to]&&e[i].to!=fa)
        {
            de[e[i].to]=(de[u]+e[i].va)%3;
            gtde(e[i].to,u);
        }
}
int clc(int u,int nw)
{
    t[0]=t[1]=t[2]=0;
    de[u]=nw;
    gtde(u,0);
    return t[1]*t[2]*2+t[0]*t[0];
}
void wk(int u)
{
    ans+=clc(u,0);
    v[u]=1;
    for(int i=h[u];i;i=e[i].ne)
        if(!v[e[i].to])
        {
            ans-=clc(e[i].to,e[i].va);
            rt=0;
            sum=si[e[i].to];
            getrt(e[i].to,0);
            wk(rt);
        }
}
int main()
{
    n=read();
    for(int i=1;i<n;i++)
    {
        int x=read(),y=read(),z=read()%3;
        add(x,y,z),add(y,x,z);
    }
    hs[0]=sum=n;
    getrt(1,0);
    wk(rt);
    int t=gcd(ans,n*n);
    printf("%d/%d",ans/t,n*n/t);
    return 0;
}