Problem Description
Professor Zhang has an undirected graph
G
with
n
vertices and
m
edges. Each vertex is attached with a weight
wi
. Let
Gi
be the graph after deleting the
i
-th vertex from graph
G
. Professor Zhang wants to find the weight of
G1,G2,...,Gn
.
The weight of a graph G is defined as follows:
1. If G is connected, then the weight of G is the product of the weight of each vertex in G .
2. Otherwise, the weight of G is the sum of the weight of all the connected components of G .
A connected component of an undirected graph G is a subgraph in which any two vertices are connected to each other by paths, and which is connected to no additional vertices in G .
The weight of a graph G is defined as follows:
1. If G is connected, then the weight of G is the product of the weight of each vertex in G .
2. Otherwise, the weight of G is the sum of the weight of all the connected components of G .
A connected component of an undirected graph G is a subgraph in which any two vertices are connected to each other by paths, and which is connected to no additional vertices in G .
Input
There are multiple test cases. The first line of input contains an integer
T
, indicating the number of test cases. For each test case:
The first line contains two integers n and m (2≤n≤105,1≤m≤2×105) -- the number of vertices and the number of edges.
The second line contains n integers w1,w2,...,wn (1≤wi≤109) , denoting the weight of each vertex.
In the next m lines, each contains two integers xi and yi (1≤xi,yi≤n,xi≠yi) , denoting an undirected edge.
There are at most 1000 test cases and ∑n,∑m≤1.5×106 .
The first line contains two integers n and m (2≤n≤105,1≤m≤2×105) -- the number of vertices and the number of edges.
The second line contains n integers w1,w2,...,wn (1≤wi≤109) , denoting the weight of each vertex.
In the next m lines, each contains two integers xi and yi (1≤xi,yi≤n,xi≠yi) , denoting an undirected edge.
There are at most 1000 test cases and ∑n,∑m≤1.5×106 .
Output
For each test case, output an integer
S=(∑i=1ni⋅zi) mod (109+7)
, where
zi
is the weight of
Gi
.
Sample Input
1 3 2 1 2 3 1 2 2 3
Sample Output
20
Author
zimpha
Source
2016 Multi-University Training Contest 2
题意:给你一个图,定义一个联通块的权值为其所有元素的乘积,一个图的权值为所有联通块权值的和,Gi为G删除i后的子图, 问你所有Gi*i的和。
分析:删除后影响图连通性的点一定是割点,在求出所有双联通分量后重新构图,每个联通分量添加一个虚点,把连通分量的每个点向虚点连边,然后我们就得到了一个和原图连通性一样的森林,在每棵树上DP即可。
题意:给你一个图,定义一个联通块的权值为其所有元素的乘积,一个图的权值为所有联通块权值的和,Gi为G删除i后的子图, 问你所有Gi*i的和。
分析:删除后影响图连通性的点一定是割点,在求出所有双联通分量后重新构图,每个联通分量添加一个虚点,把连通分量的每个点向虚点连边,然后我们就得到了一个和原图连通性一样的森林,在每棵树上DP即可。
#include <cstdio>
#include <queue>
#include <vector>
#include <cstdio>
#include <utility>
#include <cstring>
#include <iostream>
#include <algorithm>
#define INF 0x3f3f3f3f
#define MOD 1000000007
using namespace std;
bool jud[200005],iscut[200005];
int Deep,T,n,m,col,num,dfs_clock,top,bcc_cnt,low[200005],pre[200005],f[200005],bccno[200005];
long long TOT,w[200005],weight[200005],weight2[200005],ans[200005],Count[200005];
vector <int> a[200005],b[200005],bcc[200005];
struct Edge
{
int u,v;
Edge()
{
u = v = 0;
}
Edge(int x,int y)
{
u = x,v = y;
}
} S[200005];
long long ksm(long long a,long long b)
{
long long ans = 1ll;
while(b)
{
if(b & 1) ans = ans * a % MOD;
a = a * a % MOD;
b>>=1;
}
return ans;
}
int dfs(int u,int fa,const int col,const int deep)
{
Deep = max(Deep,deep);
low[u] = pre[u] = ++dfs_clock;
int child = 0;
f[u] = col;
Count[col]++;
weight[col] = weight[col] * w[u] % MOD;
for(int v : a[u])
{
if(!pre[v])
{
S[++top] = Edge(u,v);
child++;
dfs(v,u,col,deep+1);
low[u] = min(low[u],low[v]);
if(low[v] >= pre[u])
{
iscut[u] = true;
bcc[++bcc_cnt].clear();
for(;;)
{
Edge x = S[top--];
if(bccno[x.u] != bcc_cnt)
{
bcc[bcc_cnt].push_back(x.u);
bccno[x.u] = bcc_cnt;
}
if(bccno[x.v] != bcc_cnt)
{
bcc[bcc_cnt].push_back(x.v);
bccno[x.v] = bcc_cnt;
}
if(x.u == u && x.v == v) break;
}
}
}
else
if(pre[v] < pre[u] && v != fa)
{
S[++top] = Edge(u,v);
low[u] = min(low[u],pre[v]);
}
}
if(fa < 0 && child == 1) iscut[u] = 0;
return low[u];
}
void dfs2(int u,int fa)
{
jud[u] = true;
weight2[u] = w[u];
long long son = 0;
for(int v : b[u])
{
if(!jud[v])
{
dfs2(v,u);
weight2[u] = weight2[u] * weight2[v] % MOD;
son = (son + weight2[v]) % MOD;
}
}
if(fa == -1 && iscut[u]) ans[u] = (TOT + MOD - weight[f[u]] + son) % MOD;
else
if(iscut[u]) ans[u] = (TOT + MOD - weight[f[u]] + weight[f[u]]*ksm(weight2[u],MOD-2) % MOD + son) % MOD;
}
int main()
{
scanf("%d",&T);
while(T--)
{
memset(jud,0,sizeof(jud));
memset(pre,0,sizeof(pre));
memset(iscut,0,sizeof(iscut));
memset(bccno,0,sizeof(bccno));
memset(Count,0,sizeof(Count));
TOT = col = bcc_cnt = 0;
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;i++)
{
scanf("%d",&w[i]);
a[i].clear();
b[i].clear();
}
for(int i = n+1;i <= 2*n;i++) b[i].clear();
for(int i = 1;i <= m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[x].push_back(y);
a[y].push_back(x);
}
for(int i = 1;i <= n;i++)
if(!pre[i])
{
dfs_clock = 0;
weight[++col] = 1ll;
dfs(i,-1,col,1);
TOT = (TOT + weight[col]) % MOD;
}
for(int i = 1;i <= bcc_cnt;i++)
{
int u = n + i;
w[u] = 1;
for(int j = 0;j < bcc[i].size();j++)
{
int v = bcc[i][j];
b[u].push_back(v);
b[v].push_back(u);
}
bcc[i].clear();
}
for(int i = 1;i <= n;i++)
if(!jud[i]) dfs2(i,-1);
long long Ans = 0;
for(int i = 1;i <= n;i++)
{
if(Count[f[i]] == 1) Ans = (Ans + i*(TOT + MOD - w[i]) % MOD) % MOD;
else
if(iscut[i]) Ans = (Ans + i*ans[i]) % MOD;
else Ans = (Ans + i*(TOT + MOD - weight[f[i]] + weight[f[i]]*ksm(w[i],MOD-2) % MOD) % MOD ) % MOD;
}
cout<<Ans<<endl;
}
}