zoukankan      html  css  js  c++  java
  • hdu6832 图转树->树形dp算点权

    这道题比赛的时候真的很可惜,就差一点点,当时脑子胡了,边权点权傻傻分不清

    题意

    有n个点 m条边的无向图,每个点分别是0 或者 1,问所有0到1的点的距离之和是多少,每条边输入的距离就是2^(i-2)(第一行输入n,m,第二行输入n个0or1,接下来输入m行,第i行输入就是2的i-2次)输出mod 1e9+7

    思路

    其实,比赛时候把他直接转换成最小生成树,因为边是按照从小到大排序输入,所以直接用并查集那种方法生成最小生成树。

    然后计算这个节点的子节点有多少0和1,统计出来。

    接着,计算节点和他的子节点这条边做得贡献,(节点0数量 * 子节点1数量+节点1数量 * 子节点0数量)*边权之和就是答案(比赛时候点权搞错了,一直写成边权,答案输出一直不对,直接自闭)

    代码块

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<map>
    #include<queue>
    #include<algorithm>
    #define mod 1000000007
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    const int N=1e5+10;
    struct node{
        int next,to;ll w;
        node(){}
        node(int sx,int sy,ll ww):next(sx),to(sy),w(ww){}
    }a[N<<2];
    ll sum,dp[N][2],K;
    int tot,head[N],n,m,f[N];
    int b[N];
    void add(int u,int v,ll w){
        a[tot].next=head[u];
        a[tot].to=v;
        a[tot].w=w;
        head[u]=tot++;
    }
    int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
    void dfs(int u,int fa){
        dp[u][1]=dp[u][0]=0;
        dp[u][b[u]]++;
        for(int i=head[u];i!=-1;i=a[i].next){
            int v=a[i].to;if(v==fa){continue;}
            dfs(v,u);
            dp[u][1]+=dp[v][1];
            dp[u][0]+=dp[v][0];
        }
        for(int i=head[u];i!=-1;i=a[i].next){
            int v=a[i].to;if(v==fa){continue;}
            sum+=((dp[v][0]*(K-dp[v][1]))%mod*a[i].w)%mod;sum%=mod;
            sum+=((dp[v][1]*(n-K-dp[v][0]))%mod*a[i].w)%mod;sum%=mod;
        }
    }
    
    int main(){
        int T;
        scanf("%d",&T);
        while(T--){
            scanf("%d%d",&n,&m);
            tot=0;K=0;
            for(int i=1;i<=n;i++){
                scanf("%d",&b[i]);if(b[i]==1){K++;}
                head[i]=-1;f[i]=i;
            }
            sum=0;
            ll zhi=1;
            for(int i=1;i<=m;i++){
                int u,v;
                scanf("%d%d",&u,&v);
                int uu=F(u),vv=F(v);zhi*=2;zhi%=mod;
                if(uu==vv){continue;}
                f[uu]=f[vv];
                add(u,v,zhi);add(v,u,zhi);
    
            }
            dfs(1,0);
            printf("%lld
    ",sum);
        }
        return 0;
    }
    /*
    10
    3 3
    1 2 1
    2 3 1
    1 3 2
    */
    
  • 相关阅读:
    php通过ip获取地理位置的方法
    python程序怎么运行起来的
    php cURL学习 一个post提交反馈的小例子
    如何运行Python程序
    python初学者的建议
    php5.4新特性实践
    php中json_encode与json_decode注意事项
    Apanta安装Emmet(Zencoding)
    office 2013 电话激活步骤
    js中encodeURI()与encodeURIComponent()区别
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/13571907.html
Copyright © 2011-2022 走看看