聪聪可可(点分治)

来源:互联网 发布:网易邮箱服务器端口 编辑:程序博客网 时间:2024/05/21 12:51

裸题,,,不解释了

#include<cstdio>#include<iostream>#include<algorithm>#define MAXN 50005using 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;} 
原创粉丝点击