#include <stdio.h> #include <math.h> #include <string.h> #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原创,但可以转载,因为我们是兄弟。