#include
#include
#include
#define MAX 41000
#define min(a,b) (a)<(b)?(a):(b)
struct node {
int v,y;
node *next;
};
int n,m,ptr,cnt,sum,top,st[MAX];
int tot,bl[MAX],vis[MAX],minn,dp[MAX];
int dfn[MAX],low[MAX],val[MAX],index;
node *head[MAX],tree[MAX],bridge[MAX];
void Initial() {
minn = 2147483647;
cnt = sum = tot = 0;
ptr = top = index = 1;
memset(dp,0,sizeof(dp));
memset(dfn,0,sizeof(dfn));
memset(vis,0,sizeof(vis));
memset(head,NULL,sizeof(head));
}
void AddEdge(int x,int y) {
tree[ptr].v = y;
tree[ptr].next = head[x],head[x] = &tree[ptr++];
tree[ptr].v = x;
tree[ptr].next = head[y],head[y] = &tree[ptr++];
}
void Trajan(int i,int fa) {
node *p = head[i];
int v = -1,flag = 1;
st[++top] = i,vis[i] = 1;
dfn[i] = low[i] = index++;
while (p != NULL) {
if (p->v == fa && flag) { //去掉一条指向父亲的边,即允许有重边
flag = 0;
p = p->next;
continue;
}
if (vis[p->v] == 0) { //父子边
Trajan(p->v,i);
low[i] = min(low[i],low[p->v]);
if (low[p->v] > dfn[i]) {
bridge[++tot].v = i;
bridge[tot].y = p->v;
}
}
else if (vis[p->v] == 1) //返祖边
low[i] = min(low[i],dfn[p->v]);
p = p->next;
}
vis[i] = 2; //表示已缩点
if (low[i] == dfn[i]) {
cnt++;
while (v != i) {
v = st[top--];
bl[v] = cnt;
dp[cnt] += val[v];
}
}
}
void CreateNew() {
ptr = 1;
memset(head,NULL,sizeof(head));
for (int i = 1; i <= tot; ++i) {
int x = bl[bridge[i].v];
int y = bl[bridge[i].y];
AddEdge(x,y);
}
}
void Tree_DP(int v,int pa) {
node *p = head[v];
while (p != NULL) {
if (p->v != pa) {
Tree_DP(p->v,v);
dp[v] += dp[p->v];
}
p = p->next;
}
minn = min(minn,abs(sum - dp[v] * 2));
}
int main()
{
int i,j,k,a,b;
while (scanf("%d%d",&n,&m) != EOF) {
Initial();
for (i = 1; i <= n; ++i)
scanf("%d",&val[i]),sum += val[i];
for (i = 1; i <= m; ++i)
scanf("%d%d",&a,&b),AddEdge(a+1,b+1);
Trajan(1,0);
if (tot == 0) {
printf("impossible\n");
continue;
}
CreateNew();
Tree_DP(1,0);
printf("%d\n",minn);
}
}
本文ZeroClock原创,但可以转载,因为我们是兄弟。