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

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

没啥难度,只需将路径取模,开桶,统计 d[0],d[1],d[2] 的值即可.

ans = d[1]*d[2]*d[2]+d[0]*d[0]

Code:

#include<bits/stdc++.h>
#define maxn 20002
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;
int head[maxn],to[maxn],nex[maxn],val[maxn],siz[maxn]; 
int d[maxn],f[maxn],vis[maxn],dep[maxn];  
int cnt,tot,sn,n,ans,root; 
void add(int u,int v,int c){ 
    nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v,val[cnt]=c;  
}
void getdis(int u,int fa){
    ++d[dep[u]]; 
    for(int v=head[u];v;v=nex[v]){
        if(to[v]==fa||vis[to[v]]) continue;   
        dep[to[v]]=(dep[u]+val[v])%3,getdis(to[v],u);            
    }
}
int calc(int u){        
    d[0]=d[1]=d[2]=0;  
    getdis(u,0);    
    return d[0]*d[0]+d[1]*d[2]*2; 
}
void getroot(int u,int fa){
    siz[u]=1,f[u]=0; 
    for(int v=head[u];v;v=nex[v]){
        if(to[v]==fa||vis[to[v]]) continue; 
        getroot(to[v],u); 
        f[u]=max(f[u],siz[to[v]]); 
        siz[u]+=siz[to[v]]; 
    }
    f[u]=max(f[u],sn-siz[u]); 
    if(f[u]<f[root]) root=u; 
}
void dfs(int u){
    vis[u]=1; 
    dep[u]=0; 
    ans+=calc(u); 
    for(int v=head[u];v;v=nex[v])
        if(!vis[to[v]]){
            dep[to[v]]=val[v]%3; 
            ans-=calc(to[v]); 
            sn=siz[to[v]],root=0;
            getroot(to[v],0); 
            dfs(root);              
        }
}
int gcd(int a,int b){ return !b ? a : gcd(b,a%b); }
int main(){
    // setIO("input");    
    scanf("%d",&n);
    for(int i=1,a,b,c;i<n;++i) scanf("%d%d%d",&a,&b,&c),add(a,b,c%3),add(b,a,c%3);  
    f[0]=0x7f7f7f7f;  cnt=0,root=0; 
    getroot(1,0),dfs(root); 
    if(!ans) printf("0/0"); 
    else {
        int c=n*n, p=gcd(ans,n*n); 
        ans/=p,c/=p; 
        printf("%d/%d",ans,c); 
    }
    return 0; 
}

  

posted @ 2019-05-23 10:22 EM-LGH 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值