题意:给出n个点和m条无向边,每个点都有权值,要求去掉一条边,使得整个图变成两个连通块,并且两者的权值总和之差最小
**思路:**首先去掉的边必定是桥,无桥的话对应无解,有桥的话,把边双都求出来缩点,然后dfs一遍统计答案
#include<bits/stdc++.h>
using namespace std;
#define ls rt<<1
#define rs (rt<<1)+1
#define PI acos(-1)
#define eps 1e-8
#define ll long long
#define fuck(x) cout<<#x<<" "<<x<<endl;
typedef pair<int,int> pii;
const int inf=2e9;
const int maxn=1e4+10;
int d[4][2]={1,0,-1,0,0,1,0,-1};
//int lowbit(int x){return x&-x;}
//void add(int x,int v){while(x<=n)bit[x]+=v,x+=lowbit(x);}
//int sum(int x){int ans=0;while(x>=1) ans+=bit[x],x-=lowbit(x);return ans;}
inline ll read() {
ll s = 0,w = 1;
char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') w = -1;
ch = getchar();
}
while(isdigit(ch))
s = s * 10 + ch - '0',ch = getchar();
return s * w;
}
inline void write(ll x) {
if(x < 0)
putchar('-'), x = -x;
if(x > 9)
write(x / 10);
putchar(x % 10 + '0');
}
int gcd(int x,int y){
return y==0?x:gcd(y,x%y);
}
struct edge{
int u,v,nxt;
}e[maxn<<2];
int sz[maxn],bccv[maxn],val[maxn],head[maxn],dfn[maxn],low[maxn],bcc[maxn],bccn,cnt,n,m,sum,minn;
stack<int>sta;
vector<int>g[maxn];
void dfs(int now,int fa){
bool flag=0;
dfn[now]=low[now]=++cnt;
sta.push(now);
for(int i=head[now];i!=-1;i=e[i].nxt){
int v=e[i].v;
if(!dfn[v]){
dfs(v,now);
low[now]=min(low[now],low[v]);
}
else
if(v!=fa||flag)
low[now]=min(low[now],dfn[v]);
else
flag=1;
}
if(low[now]==dfn[now]){
bccn++;
for(;;){
int tmp=sta.top();sta.pop();
bcc[tmp]=bccn;
bccv[bccn]+=val[tmp];
if(tmp==now) break;
}
}
}
void dfss(int now,int fa){
sz[now]=bccv[now];
for(int i=0;i<g[now].size();i++)
{
int v=g[now][i];
if(v==fa||sz[v]!=0) continue;
dfss(v,now);
sz[now]+=sz[v];
minn=min(minn,abs(sum-sz[v]-sz[v]));
}
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF){
int tmp=0;
sum=cnt=bccn=0;
minn=2e9;
for(int i=1;i<=n;i++)
head[i]=-1,dfn[i]=0,low[i]=0,sz[i]=0,bccv[i]=0,g[i].clear();
for(int i=1;i<=n;i++)
scanf("%d",&(val[i])),sum+=val[i];
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
u++;v++;
e[++tmp]={u,v,head[u]};
head[u]=tmp;
e[++tmp]={v,u,head[v]};
head[v]=tmp;
}
for(int i=1;i<=n;i++)
if(!dfn[i])
dfs(i,-1);
for(int i=1;i<=tmp;i+=2){
int u=e[i].u,v=e[i].v;
if(bcc[u]!=bcc[v])
g[bcc[u]].push_back(bcc[v]),g[bcc[v]].push_back(bcc[u]);
}
dfss(1,-1);
if(bccn==1){
puts("impossible");
continue;
}
write(minn);
puts("");
}
return 0;
}