zoukankan      html  css  js  c++  java
  • A Very Easy Graph Problem

    A Very Easy Graph Problem

     

    题解:首先根据(2^{i})的特殊性,我们可以发现最短路其实就是最小生成树上的路,那么我们就可以先把图换成最小生成树;然后我们看一条边要经过几次,就是要看一条边对答案的贡献:某一条边被遍历的次数必定是这条边下面的所有权值1的点的个数 * 这条边上面所有权值0的点的个数 + 下面所有权值0的点的个数 * 上面所有权值1的点的个数(这里我们自定义一个根来看),那么就是要(dfs)进行统计了:统计每个点以及它所有子树的权值为1的点的个数和以及权值0的点的个数和。

    AC_Code:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define endl '
    '
    const int mod=1e9+7;
    const int maxn = 2e5+10;
    
    vector<ll>G[maxn];
    
    ll w[maxn];
    ll a[maxn],u[maxn],v[maxn];
    
    ll fa[maxn],dfn[maxn];
    bool is[maxn];
    
    ll num[maxn][2],cnt,sum[2];
    
    ll find_fa(ll u){
        if( fa[u]==u ) return u;
        return fa[u]=find_fa(fa[u]);
    }
    
    void dfs(ll now,ll fa){
        dfn[now]=++cnt;
        num[now][0] = (a[now]==0);
        num[now][1] = (a[now]==1);
    
        for(size_t i=0;i<G[now].size();i++){
            ll to=G[now][i];
            if( to==fa ) continue;
            dfs(to,now);
            num[now][0] += num[to][0];
            num[now][1] += num[to][1];
        }
    }
    
    ll qpow(ll a,ll b){
        ll res=1;
        while(b){
            if( b&1 ) res=res*a%mod;
            a=a*a%mod;
            b>>=1;
        }
        return res;
    }
    
    int main()
    {
        for(ll i=0;i<maxn;i++){
            w[i]=i;
        }
    
        ll t; cin>>t;
        while( t-- ){
            ll n,m; cin>>n>>m;
            sum[0]=sum[1]=0;
    
            for(ll i=1;i<=n;i++){
                cin>>a[i];
                sum[0] += (a[i]==0);
                sum[1] += (a[i]==1);
                fa[i]=i;
                G[i].clear();
            }
    
            memset(is,false,sizeof(is));
            for(ll i=1;i<=m;i++){
                cin>>u[i]>>v[i];
                ll fu=find_fa(u[i]);
                ll fv=find_fa(v[i]);
    
                if( fu==fv ) continue;
                fa[fv]=fu;
                is[i]=true;
                G[u[i]].push_back(v[i]);
                G[v[i]].push_back(u[i]);
            }
    
            cnt=0;
            dfs(1,0);
            ll ans=0;
    
            for(ll i=1;i<=m;i++){
                if( !is[i] ) continue;
                ll fa=u[i], son=v[i];
                if( dfn[fa]>dfn[son] ) swap(fa,son);
                ll fa0 = sum[0]-num[son][0];
                ll fa1 = sum[1]-num[son][1];
    
                ans = (ans + qpow(2,w[i])*(fa0*num[son][1]%mod)%mod)%mod;
                ans = (ans + qpow(2,w[i])*(fa1*num[son][0]%mod)%mod)%mod;
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    shell备份数据库
    inux系统设置只让一个固定的ip通过ssh登录和限制连接数量
    linux服务器配置可以执行java的jar包
    sql 查询多久之前的数据
    shell将sql查询结果存放到excel中
    shell编程从初学到精通
    Redis设置键的过期时间
    Java使用redis存取集合对象
    Jpa 连接数据库自动生成实体类
    Idea 开启Run Dashboard
  • 原文地址:https://www.cnblogs.com/wsy107316/p/13460072.html
Copyright © 2011-2022 走看看