题意:给出一个图,求一个很奇怪的权重。
(1).连通块的权重是这个块里面每个节点的权重乘起来Gi.
(2).每个点去掉之后会有一个权重Zi,Zi的值是去掉这个点之后Gi的和。
(3).求Sum(i*Zi)
题解:枚举割点,统计。
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <iostream>
using namespace std;
#define N 100100
#define MOD 1000000007
typedef long long LL;
class Solution{
public:
vector<vector<int> >tr;
vector<int> w;
vector<LL> f,fm,ret;
vector<int> dfn,low;
vector<int> conBlock;
vector<bool> vi;
LL mul;
int n,idx,stp;
LL powMod(LL x,LL a,LL mod){
LL ret = 1;
x %= mod;
while(a){
if(a&1) ret = ret*x%mod;
x = x*x%mod;
a>>=1;
}
return ret;
}
LL ni(LL x){
return powMod(x,MOD-2,MOD);
}
void init(int n){
this->n=n;
tr = vector<vector<int> >(n+1);
w = low = dfn = vector<int>(n+1,0);
fm = vector<LL>(n+1,1);
ret = vector<LL>(n+1,0);
f = vector<LL>(n+1,-1);
vi = vector<bool>(n+1,false);
idx = 1;
}
void readIn(){
int n,m;
scanf(" %d %d",&n,&m);
init(n);
for(int i=1;i<=n;i++){
scanf(" %d",&w[i]);
}
for(int i=1;i<=m;i++){
int x,y;
scanf(" %d %d",&x,&y);
tr[x].push_back(y);
tr[y].push_back(x);
}
}
void tarjan(int st,int ff){
conBlock.push_back(st);
dfn[st] = low[st] = idx++;
mul = mul * w[st]%MOD;
for(int i=0;i<(int)tr[st].size();i++){
int to = tr[st][i];
if(to==ff) continue;
if(dfn[to]==0){
LL mem = mul;
tarjan(to,st);
if(low[to]>=dfn[st]){
LL tmp = mul*ni(mem)%MOD;
if(f[st]==-1) f[st] = 0 ;
f[st]=(f[st]+tmp)%MOD;
fm[st] = fm[st]*tmp%MOD;
}
low[st]=min(low[to],low[st]);
}
low[st] = min(dfn[to],low[st]);
}
}
void dfs(int st,int ff){
mul = mul*w[st]%MOD;
vi[st] = true;
for(int i=0;i<(int)tr[st].size();i++){
int to = tr[st][i];
if(to==ff) continue;
if(vi[to]) continue;
dfs(to,st);
}
}
void solve(){
LL talMul = 0;
for(int i=1;i<=n;i++){
if(!vi[i]){
mul = 1;
dfs(i,-1);
talMul = (talMul+mul)%MOD;
}
}
//printf("totalMul:%I64d\n",talMul);
for(int i=1;i<=n;i++){
if(dfn[i]==0){
//stp = i;
conBlock.clear();
mul = 1;
tarjan(i,-1);
LL conTalMul = (talMul-mul+MOD)%MOD;
if(conBlock.size()==1){
ret[i] = conTalMul;
continue;
}
for(int j=0;j<(int)conBlock.size();j++){
int p = conBlock[j];
if(f[p]==-1){//不是割点
ret[p] = (conTalMul+mul*ni(w[p])%MOD)%MOD;
continue;
}
if(p==i){
ret[p] = (f[p]+conTalMul)%MOD;//根节点一定是割点
}else{
ret[p] = (f[p]+mul*ni(fm[p]*w[p]%MOD)%MOD+conTalMul)%MOD;
}
}
}
}
LL ans = 0;
for(int i=1;i<=n;i++){
//printf("ret[%d]:%I64d ",i,ret[i]);
ans += ret[i]*i%MOD;
}
printf("%I64d\n",ans%MOD);
fflush(stdout);
}
};
int main(){
int T;
scanf(" %d",&T);
while(T--){
Solution sol;
sol.readIn();
sol.solve();
}
return 0;
}
/*
2
3 2
1 2 3
1 2
2 3
3 3
1 2 3
1 2
2 3
3 1
3 1
1 2 3
1 2
*/