zoukankan      html  css  js  c++  java
  • [BZOJ 2152] 聪聪可可

    Link:

    BZOJ 2152 传送门

    Solution:

    直接上点分治就行了(其实也可以树形$dp$)

    其中对于穿过重心的边的统计类似于树形$dp$的计算方式:

    将当前子树中模3分别为0/1/2的边与之前所有子树产生的边进行组合

    Code:

    //by NewErA 
    #include <bits/stdc++.h>
    
    using namespace std;
    typedef pair<int,int> P;
    const int INF=1<<27;
    const int MAXN=20005;
    vector<P> G[MAXN];
    int x,y,z,n,sz[MAXN],vis[MAXN],mx_sub[MAXN],v_sum=0,res=0,root;
    int dist[MAXN],f[MAXN][5];
    
    void getroot(int x,int anc)
    {
        sz[x]=1;mx_sub[x]=0;  //mx_sub要重新初始化
        for(int i=0;i<G[x].size();i++)
        {
            int v=G[x][i].first;
            if(v==anc || vis[v]) continue;
            getroot(v,x);sz[x]+=sz[v];
            mx_sub[x]=max(mx_sub[x],sz[v]);
        }
        mx_sub[x]=max(mx_sub[x],v_sum-sz[x]);
        if(mx_sub[x]<mx_sub[root]) root=x;
    }
    
    void cal(int x,int anc,int val,int pos)
    {
        f[pos][val%3]++;
        for(int i=0;i<G[x].size();i++)
        {
            int v=G[x][i].first;
            if(v==anc || vis[v]) continue;
            cal(v,x,val+G[x][i].second,pos);
        }
    }
    
    void solve(int x)
    {
        vis[x]=true;
        for(int i=0;i<G[x].size();i++)
        {
            int v=G[x][i].first;
            if(vis[v]) continue;
            
            int t0=f[x][0],t1=f[x][1],t2=f[x][2];
            cal(v,x,G[x][i].second,x);
            res+=(t0+1)*(f[x][0]-t0)+t2*(f[x][1]-t1)+t1*(f[x][2]-t2);
            
            v_sum=sz[v];getroot(v,root=0);
            solve(root);//注意这里的变量名
        }
    }
    
    int GCD(int a,int b){return (a%b)?GCD(b,a%b):b;}
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            G[x].push_back(P(y,z%3));G[y].push_back(P(x,z%3));
        }
        mx_sub[0]=v_sum=n,getroot(1,root=0);
        solve(root);res=res*2+n;
        
        int gcd=GCD(res,n*n);
        cout << res/gcd << '/' << n*n/gcd;
        return 0;
    }
  • 相关阅读:
    Nova官方资料入口处
    LeetCode 有效的数独
    LeetCode 两数之和
    LeetCode 移动零
    安装OpenStack Queens版本的教程推荐
    删除排序数组中的重复项
    (转载)OpenStack client 调用分析
    (转载)基于Linux C的socket抓包程序和Package分析
    Maven的具体使用和优点
    关于 Javascript 学习,有哪些好的博客或者网站推荐?
  • 原文地址:https://www.cnblogs.com/newera/p/9302968.html
Copyright © 2011-2022 走看看