• BZOJ 2152 聪聪可可(点分治)


    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2152

    【题目大意】

      给出一棵树,问任取两点之间距离为3的倍数的概率是多少

    【题解】

      树分治统计模3之后不同的链长计算答案,最后和总数求个gcd化简即可。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <cstring> 
    using namespace std;
    typedef pair<int,int> P;
    #define ff first
    #define ss second
    const int N=20010;
    int n,cnt,ans,root,sum;
    int size[N],dp[N],d[N],t[5],vis[N];
    vector<P> G[N];
    void add_edge(int u,int v,int w){
        G[u].push_back(P(v,w));
        G[v].push_back(P(u,w));
    }
    void getroot(int x,int fx){
        size[x]=1; dp[x]=0;
        for(int i=0;i<G[x].size();i++){
            int y=G[x][i].ff,z=G[x][i].ss;
            if(!vis[y]&&y!=fx){
                getroot(y,x);
                size[x]+=size[y];
                dp[x]=max(dp[x],size[y]);
            }
        }dp[x]=max(dp[x],sum-size[x]);
        if(dp[x]<dp[root])root=x;
    }
    void getdeep(int x,int fx){
        t[d[x]]++;
        for(int i=0;i<G[x].size();i++){
            int y=G[x][i].ff,z=G[x][i].ss;
            if(!vis[y]&&y!=fx){
                d[y]=(d[x]+z)%3;
                getdeep(y,x);
            }
        }
    }
    int cal(int x,int dx){
        t[0]=t[1]=t[2]=0;
        d[x]=dx;
        getdeep(x,0);
        return t[1]*t[2]*2+t[0]*t[0];
    }
    void solve(int x){
        ans+=cal(x,0); vis[x]=1;
        for(int i=0;i<G[x].size();i++){
            int y=G[x][i].ff,z=G[x][i].ss;
            if(!vis[y]){
                ans-=cal(y,z);
                root=0;sum=size[y];
                getroot(y,0);
                solve(root);
            }
        }
    }
    int main(){
        while(~scanf("%d",&n)){
        	for(int i=1;i<=n;i++)G[i].clear();
            for(int i=1;i<n;i++){
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                add_edge(u,v,w%3);
            }dp[0]=sum=n; ans=0;
            memset(vis,0,sizeof(vis));
            getroot(1,0);
            solve(root);
            int t=__gcd(ans,n*n);
            printf("%d/%d
    ",ans/t,n*n/t);
        }return 0;
    }
  • 相关阅读:
    Homework
    自我介绍,恩。。算是吧
    What ASP.NET Developers Should Know About JavaScript
    短信猫软件的C#实现系列文章
    装箱与拆箱
    HTML的基本标签
    CSS基础用法
    ajaxToolkit:AutoCompleteExtender 用法详解
    比较强大的分页存储过程
    不知道写点什么
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj2152.html
Copyright © 2020-2023  润新知