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

裸的点分治,运算在模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;
}

猜你喜欢

转载自www.cnblogs.com/lokiii/p/9642509.html