A Very Easy Graph Problem
Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 427 Accepted Submission(s): 153
Problem Description
An undirected connected graph has n nodes and m edges, The i-th edge’s length is 2i. Each node i has a value ai, which is either 0 or 1. You need to calculate:
∑i=1n∑j=1nd(i,j)×[ai=1∧aj=0]
d(i,j) indicates the shortest distance between i and j. [ ] is the Iverson bracket. ∧ indicates 𝙰𝙽𝙳.
Because the answer may be too large, please output the answer modulo 109+7.
Input
The first line contains one integer T(1≤T≤8),indicating the number of test cases.
The second line contains two ingeters n,m(1≤n≤105,1≤m≤2×105).
The third line contains n positive integers a1,a2,…,an(ai=0 or 1) —— the value of the nodes.
The following m lines contain two ingeters u,v(1≤u,v≤n), and the i-th line represents the i-th undirected edge’s length is 2i, between node u and v.
The sum of n,m is no more than 2×105.
Output
Print a single integer—— the value of the answer modulo 109+7.
Sample Input
1
3 2
0 1 0
3 1
3 2
Sample Output
10
题解:
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int maxn = 1e5+10;
int n,m;ll ans=0;
int zero=0,one=0;
vector<pair<int,ll>>G[maxn];
int dp[maxn][2],col[maxn],f[maxn];
void dfs(int u,int f){//f为上一个点
dp[u][0]=dp[u][1]=0;//dp中记录记录的是经过每条边的黑白点的个数
dp[u][col[u]]++;
for(auto it:G[u]){
int v=it.first;
if(v==f)continue;
dfs(v,u);
dp[u][0]+=dp[v][0];
dp[u][1]+=dp[v][1];
}
for(auto it:G[u]){
int v=it.first;
if(v==f)continue;
ans=(ans+1ll*dp[v][0]*(one-dp[v][1])%mod*it.second)%mod;
ans=(ans+1ll*dp[v][1]*(zero-dp[v][0])%mod*it.second)%mod;
}
}
int find(int x){return f[x]==x?x:(f[x]=find(f[x]));}
int main(){
//freopen("./data/1.in","r",stdin);
int T;cin>>T;
while(T--){
ans=0,zero=one=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)dp[i][0]=dp[i][1]=0,G[i].clear();
for(int i=1;i<=n;i++)scanf("%d",&col[i]),f[i]=i;
for(int i=1;i<=n;i++){
if(col[i])one++;
else zero++;
}
ll val=1;
for(int i=1;i<=m;i++){
int u,v;scanf("%d%d",&u,&v);
val=val*2%mod;
int fu=find(u),fv=find(v);
if(fu==fv)continue;
f[fu]=fv;
G[u].push_back(make_pair(v,val));//存放的是满足最小生成树中的点和边
G[v].push_back(make_pair(u,val));
}
dfs(1,-1);
printf("%lld\n",ans);
}
}