[国家集训队] 聪聪可可

算是点分治的模板吧,把每条边都模3归类就可以了。
模板我是学yyb dalao的。
计算calc函数的时候有一点改进就是不需要把所有的节点的枚举一遍了,可以直接通过相互关系计算得出qwq。
至于为什么前面不同的要乘以二呢?大家可以思考一下,原先我们要枚举每个点然后是一个平方的算法,然后自然是值不同的话会被计算两次,值相同的只有一次啦qwq(不理解的话可以模拟一下过程??)
代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100010
using namespace std;
inline int read()
{
    int f=1,x=0; char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
int n,m,t,tot,root,minr,size;
int done[MAXN],head[MAXN],s[4],siz[MAXN],num[4];
struct Edge{int nxt,to,dis;}edge[MAXN<<1];
inline void add(int from,int to,int dis){edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;}
inline void get_rt(int x,int fa)
{
    siz[x]=1;
    int res=0;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==fa||done[v]) continue;
        get_rt(v,x);
        res=max(res,siz[v]);
        siz[x]+=siz[v];
    }
    res=max(res,size-siz[x]);
    if(res<minr) minr=res,root=x;
}
inline void get_dep(int x,int fa,int dep)
{
    s[dep%3]++;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(v==fa||done[v]) continue;
        get_dep(v,x,dep+edge[i].dis);
    }
}
inline void calc(int x,int op,int sum)
{
    memset(s,0,sizeof(s));
    get_dep(x,x,0);
    if(op)
    {
        num[0]+=2*s[1]*s[2]+s[0]*s[0];
        num[1]+=2*s[0]*s[1]+s[2]*s[2];
        num[2]+=2*s[0]*s[2]+s[1]*s[1];
    }
    else
    {
        sum%=3;
        num[(0+sum)%3]-=2*s[1]*s[2]+s[0]*s[0];
        num[(1+sum)%3]-=2*s[0]*s[1]+s[2]*s[2];
        num[(2+sum)%3]-=2*s[0]*s[2]+s[1]*s[1];
    }
}
inline void dfs(int x)
{
    calc(x,1,0);
    done[x]=1;
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int v=edge[i].to;
        if(done[v]) continue;
        calc(v,0,edge[i].dis*2);
        minr=n,size=siz[v];
        get_rt(v,x);
        dfs(root);
    }
}
inline int gcd(int x,int y)
{
    return y?gcd(y,x%y):x;
}
int main()
{
  
    n=read();
    int u,v,w;
    for(int i=1;i<n;i++)
    {
        u=read(),v=read(),w=read();
        add(u,v,w),add(v,u,w);
    }
    minr=size=n;
    get_rt(1,1);
    dfs(root);
    int x=num[0];
    int y=num[0]+num[1]+num[2];
    int cur=gcd(x,y);
    printf("%d/%d
",x/cur,y/cur);
    return 0;
}

原文地址:https://www.cnblogs.com/fengxunling/p/10274231.html