/*先求出双联通缩点,然后进行树形dp*/ #include<stdio.h> #include<string.h> #include<math.h> #define inf 0x3fffffff #define N 11000 struct node { int u,v,next; } bian[N*4],edge[N*4]; int head[N],yong,dfn[N],low[N],index,f[N*4],cnt,n,num[N]; int yon; int belong[N],tot[N]; int visit[N],dp[N]; void init() { memset(head,-1,sizeof(head)); yong=0; index=0; cnt=0; memset(dfn,0,sizeof(dfn)); memset(f,0,sizeof(f)); memset(low,0,sizeof(low)); } int Min(int a,int b) { return a>b?b:a; } void addedge(int u,int v) //一次建图 { bian[yong].u=u; bian[yong].v=v; bian[yong].next=head[u]; head[u]=yong++; } void tarjan(int u,int pre ) //tarjan算法求桥 { dfn[u]=low[u]=++index; int i; for(i=head[u]; i!=-1; i=bian[i].next) { int v=bian[i].v; if(i==(pre^1))continue; if(!dfn[v]) { tarjan(v,i); low[u]=Min(low[u],low[v]); if(low[v]>dfn[u]) { cnt=1;//是否存在桥 f[i]=f[i^1]=1;//标记桥 } } else low[u]=Min(low[u],dfn[v]); } return ; } void dfs(int u,int pre) { belong[u]=cnt;//缩 tot[cnt]+=num[u];//记录缩点的权值 int i,v; for(i=head[u]; i!=-1; i=bian[i].next) { v=bian[i].v; if(!f[i]&&!belong[v]&&i!=(pre^1)) dfs(v,i); } return ; } void addedge1(int u,int v) //二次建图 { edge[yon].u=u; edge[yon].v=v; edge[yon].next=head[u]; head[u]=yon++; } void slove() { int i; memset(belong,0,sizeof(belong)); memset(tot,0,sizeof(tot)); cnt=0; for(i=1; i<=n; i++) if(!belong[i]) //缩点 { cnt++; dfs(i,-1); } memset(head,-1,sizeof(head)); yon=0; for(i=0; i<yong; i++) //重新建图 { int u=bian[i].u,v=bian[i].v; if(belong[u]!=belong[v]) { addedge1(belong[u],belong[v]); addedge1(belong[v],belong[u]); // printf("%d %d ",belong[u],belong[v]); } } return ; } int dfs1(int u) //为树形图求出他和他的子节点的权值 { visit[u]=1; int i,v,sum=0; sum+=tot[u]; for(i=head[u]; i!=-1; i=edge[i].next) { v=edge[i].v; if(!visit[v]) { sum+=dfs1(v); } } //printf("%d %d ",u,sum); dp[u]=sum; return sum; } int main() { int m,i,j,k,a,b,c,sum,minn; while(scanf("%d%d",&n,&m)!=EOF) { sum=0; init(); for(i=1; i<=n; i++) { scanf("%d",&num[i]); sum+=num[i]; } while(m--) { scanf("%d%d",&a,&b); a++; b++; addedge(a,b); addedge(b,a); } tarjan(1,-1); if(cnt==0) //如果不存在桥 { printf("impossible "); continue; } slove(); memset(visit,0,sizeof(visit)); dfs1(1); minn=inf; for(i=1; i<=cnt; i++) { // printf("%d ",dp[i]); minn=Min(minn,fabs(sum*1.0-2.0*dp[i]));//求最优 } printf("%d ",minn); } return 0; }