聪聪可可(点分治)

裸题,,,不解释了

#include<cstdio>
#include<iostream>
#include<algorithm>
#define MAXN 50005
using namespace std;

int F[MAXN][4],head[MAXN],son[MAXN],f[MAXN];
bool can[MAXN];
int root ,n,all,M,Son,c,cnt,ans;

struct N{
    int to,ne,w;
}e[MAXN<<1];

inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
            ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}

void add(int x,int y,int w)
{
    cnt++;
    e[cnt].ne=head[x];
    e[cnt].w=w;
    e[cnt].to=y;
    head[x]=cnt;
}

void get(int k,int fa)//找重心
{
    son[k]=1;
    f[k]=0;
    for(int i=head[k];i;i=e[i].ne)
    {
        int y=e[i].to;
        if(fa==y||can[y])continue;
        get(y,k);
        son[k]+=son[y];
        f[k]=max(son[y],son[k]);
    }
    f[k]=max(all-son[k],f[k]);
    if(f[k]<f[root])root=k;
}

void dfs(int k,int fa,int p,int now)//递归找点
{
    F[p][now]++;
    for(int i=head[k];i;i=e[i].ne)
    {
        int to=e[i].to;
        if(to==fa||can[to])continue;
        dfs(to,k,p,(now+e[i].w)%3);
    }
}

void work(int k)
{
    can[k]=1;
    for(int i=head[k];i;i=e[i].ne)
    {
        int to=e[i].to;
        if(can[to])continue;
        int N0=F[k][0],N1=F[k][1],N2=F[k][2];
        dfs(to,k,k,e[i].w);
        ans+=(N0+1)*(F[k][0]-N0)+N2*(F[k][1]-N1)+N1*(F[k][2]-N2);//2的与余1的结合,整除的与整除的结合
        f[root=0]=n+1;
        all=son[to];
        get(to,-1);
        work(root); 
    }
}

int main()
{
    //scanf("%d",&n);
    n=read();
    int a,b,w;
    for(int i=1;i<n;i++)
    {
        //scanf("%d%d%d",&a,&b,&w);
        a=read();
        b=read();
        w=read();
        add(a,b,w%3);
        add(b,a,w%3);
    }
    f[root=0]=n+1;
    all=n;
    get(1,-1);
    work(root);
    M=n*n;
    Son=ans*2+n;
    c=__gcd(M,Son);
    M/=c;
    Son/=c; 
    printf("%d/%d\n",Son,M);
    return 0;
} 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值