点分治练习2——P2634 [国家集训队]聪聪可可

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Love_mona/article/details/81283414

蒟蒻的垂死挣扎

这道题一样是模板题,在树上大力点分一波,记录权值和mod 3的路径条数,每次计算贡献即可。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#define ll long long
#define MOD 998244353
#define N 20010
#define M 10001000
#define RG register

using namespace std;

inline ll read(){
    RG ll x=0,o=1; RG char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if(ch=='-') o=-1,ch=getchar();
    while(ch>='0'&&ch<='9') x=((x<<3)+(x<<1))+ch-'0',ch=getchar();
    return x*o;
}

int n,root,top,t1[4],t2[4],first[N],Max=1e9,siz[N],Siz,vis[N],ans,st[N],tot;
struct mona { int nxt,en; int w; } s[N<<1];
inline void Insert(int x,int y,int w) { s[++top]=(mona) { first[x],y,w },first[x]=top; }
inline int Gcd(int x,int y) { while(y^=x^=y^=x%=y); return x; }

inline void Getroot(int k,int fa){
    siz[k]=1; int mmax=0;
    for(RG int i=first[k];i;i=s[i].nxt){
        int en=s[i].en; if(en==fa||vis[en]) continue ;
        Getroot(en,k),siz[k]+=siz[en],mmax=max(mmax,siz[en]);
    }   mmax=max(mmax,Siz-siz[k]);
    if(mmax<Max) Max=mmax,root=k; return ;
}

inline void Getdis(int k,int fa,int D){
    int now=D%3;
    ++t2[now],ans+=t1[ (now!=0) ? (3-now):0 ];
    for(RG int i=first[k];i;i=s[i].nxt){
        int en=s[i].en; if(en==fa||vis[en]) continue ;
        Getdis(en,k,D+s[i].w);
    }   return ;
}

inline void Divide(int k){
    vis[k]=1; for(RG int i=0;i<=2;++i) t1[i]=0;
    for(RG int i=first[k];i;i=s[i].nxt){
        int en=s[i].en; if(vis[en]) continue ;
        for(RG int j=0;j<=2;++j) t2[j]=0; Getdis(s[i].en,0,s[i].w); 
        for(RG int j=0;j<=2;++j) t1[j]+=t2[j];
    }   ans+=t1[0];
    for(RG int i=first[k];i;i=s[i].nxt){
        int en=s[i].en; if(vis[en]) continue ;
        Siz=(siz[k]>=siz[en])?siz[en]:Siz-siz[k];
        Max=1e9,root=0,Getroot(en,0),Divide(root);
    }
}

int main(){
    n=Siz=read();
    for(RG int i=1;i<n;++i){
        int x=read(),y=read(),z=read();
        Insert(x,y,z),Insert(y,x,z);
    }   Getroot(1,0),Divide(root); ans<<=1,ans+=n;
    int gcd=Gcd(ans,n*n); 
    cout<<ans/gcd<<'/'<<n*n/gcd;
}

猜你喜欢

转载自blog.csdn.net/Love_mona/article/details/81283414