P2634 [国家集训队]聪聪可可 点分治

  

点分治模板题

注意calc计算的时候  注意一个端点经过x的链也是要统计的!!

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i>=(b);--i)
#define ll long long
#define see(x) (cerr<<(#x)<<'='<<(x)<<endl)
#define inf 0x3f3f3f3f
#define CLR(A,v)  memset(A,v,sizeof A)
//////////////////////////////////
const int N=2e6+10;
int n,m,cnt,d[N],head[N],pos,siz[N],sum,x,y,z,ans,vis[N],t[5],root,maxson[N];
struct Edge{int to,nex,v;}edge[N<<1];
void add(int a,int b,int c){edge[++pos]=(Edge){b,head[a],c};head[a]=pos;}
void getroot(int x,int fa)
{    
    siz[x]=1;maxson[x]=0;
    for(int i=head[x];i;i=edge[i].nex)
    {
        int v=edge[i].to;
        if(vis[v]||v==fa)continue;
        getroot(v,x);siz[x]+=siz[v];
        maxson[x]=max(maxson[x],siz[v]);
    }
    maxson[x]=max(maxson[x],sum-siz[x]);
    if(maxson[x]<maxson[root])root=x;
}
void getdis(int x,int fa)
{
    t[d[x]]++;
    for(int i=head[x];i;i=edge[i].nex)
    {
        int v=edge[i].to;
        if(vis[v]||v==fa)continue;
        d[v]=(d[x]+edge[i].v)%3;
        getdis(v,x);
    }
}
int calc(int x,int v)
{
    t[0]=t[1]=t[2]=0;
    d[x]=v%3;
    getdis(x,0);
    return t[0]*t[0]+t[1]*t[2]*2;
}
void solve(int x)
{    
    see(x);
    vis[x]=1;ans+=calc(x,0);
    for(int i=head[x];i;i=edge[i].nex)
    {
        int v=edge[i].to;
        if(vis[v])continue;
        ans-=calc(v,edge[i].v);
        root=0;sum=siz[v];
        getroot(v,x);
        solve(root);
    }
}
int main()
{
    scanf("%d",&n);
    rep(i,1,n-1)
    scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
    sum=maxson[0]=n;//一定要初始化  为了每次求根的时候的初始化
    root=0;
    getroot(1,0);
    solve(root);
    printf("%d/%d
",ans/__gcd(n*n,ans),n*n/__gcd(n*n,ans));
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/bxd123/p/11536541.html