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 '\n'
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;
}

 

posted @ 2020-08-08 19:52  swsyya  阅读(230)  评论(0编辑  收藏  举报

回到顶部