清题所用题解:
https://blog.csdn.net/qq_43906000/article/details/107870347
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:
∑ni=1∑nj=1d(i,j)×[ai=1∧aj=0]
d(i,j)ndicates the shortest distance between i and j. [ ] is the Iverson bracket. ∧ indicates AND.
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
思路:
对于第i条边而言,如果它所连接的u,v两点在第i条边之前就已经被连接了,那么根据2^ 1 +2^ 2+……2 ^ (i-1)<2^i,这条边就是可以直接扔掉的,由此构造kruskal生成树,然后用dfs来处理,我们可以计算一下每条边的左右两侧各有多少黑点和白点。
代码:
#include<bits/stdc++.h>
#include<string>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=2e5+10;
struct node{
int u,v,w;
}a[N*2];
struct tree{
int to,ne,w;
}b[N];
int cnt=0,h[N],color[N];
int color0[N],color1[N],fa[N];
vector<int>edge;
int n,m;
void add(int u,int v,int w){
b[cnt]=tree{v,h[u],w};
h[u]=cnt++;
}
void init(){
cnt=0;
edge.clear();
memset(h,-1,sizeof(h));
for(int i=1;i<=n;i++)fa[i]=i;
}
int find(int x){
if(fa[x]==x)return x;
else return fa[x]=find(fa[x]);
}
void kruskal(int m,int n){
int num=0;
for(int i=0;i<=m;i++){
int fu=find(a[i].u);
int fv=find(a[i].v);
if(fu==fv)continue;
fa[fu]=fv;
num++;
add(a[i].u,a[i].v,a[i].w);
add(a[i].v,a[i].u,a[i].w);
edge.push_back(a[i].w);
if(num==n-1)break;
}
}
ll quick(ll a,ll b){
ll ans=1;
a=a%mod;
while(b){
if(b&1)ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
struct Col
{
int nbw,nbb;
Col operator+(const Col &a)const{
return Col{nbw+a.nbw,nbb+a.nbb};
}
};
Col dfs(int x,int fa)
{
Col cl=Col{0,0};
for (int i=h[x]; i!=-1; i=b[i].ne){
int v=b[i].to;
// printf("v=%d,fa=%d\n",v,fa);
if (v==fa) continue;
Col p=dfs(v,x);
cl=cl+p;
color0[b[i].w]=p.nbw;
color1[b[i].w]=p.nbb;
// printf("v=%d,fa=%d,p.nbw=%d,p.nbb=%d\n",v,fa,p.nbw,p.nbb);
}
if (color[x]==0) return cl+Col{1,0};
return cl+Col{0,1};
}
int main()
{
int t;
cin>>t;
init();
while(t--){
cin>>n>>m;
init();
int black=0,white=0;
for(int i=1;i<=n;i++){
cin>>color[i];
if(color[i]==0)white++;
else black++;
}
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
a[i-1]=node{x,y,i};
}
kruskal(m-1,n);
dfs(1,-1);
ll ans=0;
for (auto x:edge){
int wt=white-color0[x];
int bk=black-color1[x];
ans=(ans+(wt*color1[x]%mod)*quick(2,x)%mod)%mod;
ans=(ans+(bk*color0[x]%mod)*quick(2,x)%mod)%mod;
}
printf("%lld\n",ans);
}
}