# HDU-6832 A Very Easy Graph Problem【2020 Multi-University Training Contest 6】【最小生成树】【并查集】【dfs】

HDU-6832

## 题意

d(i，j)为点i到j的最短路的值
1<=n<=1e5
1<=m<=2e5

## 代码

/*
* @author: arc
* @date: 2020-08-06 19:34:17
*/
#include<cstdio>
#include<vector>
using namespace std;
typedef long long ll,LL;
#define mod 1000000007
const int maxn = 1e5+10;

int r[maxn];
int a[maxn];
vector<pair<int, ll> > G[maxn];
int cnt[maxn][2];
ll zero, one;
ll ans = 0;

void init(int n){
for(int i = 1; i <= maxn-5; i++){
r[i] = i;
G[i].clear();
cnt[i][0] = cnt[i][1] = 0;
}
}

int __find(int k){
if(r[k] == k) return k;
return r[k] = __find(r[k]);
}

void __merge(int a, int b){
int fa = __find(a);
int fb = __find(b);
if(fa != fb) r[fb] = fa;
}

ll dfs(int u, int f){
cnt[u][0] = cnt[u][1] = 0;
cnt[u][a[u]]++;
for(auto it: G[u]){
int v = it.first;
if(v == f)
continue;
dfs(v, u);
cnt[u][0] += cnt[v][0];
cnt[u][1] += cnt[v][1];
}
for(auto it: G[u]){
int v = it.first;
if (v == f) continue;
ans = (ans + 1LL * cnt[v][1] * (zero - cnt[v][0]) % mod * it.second) % mod;
ans = (ans + 1LL * cnt[v][0] * (one - cnt[v][1]) % mod * it.second) % mod;
}
return ans;
}

int main(){
#ifdef ONLINE_JUDGE
#else
freopen("temp.in","r",stdin);
freopen("temp.out","w",stdout);
#endif
int cas;
scanf("%d", &cas);
while(cas--){
int n, m;
scanf("%d%d", &n, &m);
init(n);
zero = one = 0;
for (int i = 1; i <= n; i++){
scanf("%d", &a[i]);
if(a[i] == 0){
zero++;
} else {
one++;
}
}
int u, v;
ll val = 1;
for (int i = 1; i <= m; i++){
scanf("%d%d", &u, &v);
val *= 2;
val %= mod;
if(__find(u) != __find(v)){
__merge(u, v);
G[u].push_back(make_pair(v, val));
G[v].push_back(make_pair(u, val));
}
}
ans = 0;
dfs(1, -1);
printf("%lld\n", ans);
}
return 0;
}


11-09 1212
10-12 6231
10-08 651
10-04 2489