1 /********************************************************** 2 题目: 考研路茫茫——空调教室(hdu 2242) 3 链接: http://acm.hdu.edu.cn/showproblem.php?pid=2242 4 算法: 双联通 5 思路: 找到桥,然后计算桥两边的差,在把桥一边 6 的值压缩到和另一边相邻的数上。 7 8 ***********************************************************/ 9 10 #include<cstdio> 11 #include<iostream> 12 #include<cstring> 13 #include<algorithm> 14 #include<vector> 15 #include<stack> 16 using namespace std; 17 18 const int mx=100005; 19 int a[mx]; 20 stack<int>s; 21 vector<int>g[mx]; 22 int flag,dfs_cut; 23 int dfn[mx],low[mx],vs[mx]; 24 int ans,sum; 25 26 void Init(int n) 27 { 28 int i; 29 sum=0; 30 for (i=0;i<n;i++) 31 { 32 g[i].clear(); 33 scanf("%d",&a[i]); 34 sum+=a[i]; 35 } 36 memset(dfn,0,sizeof(dfn)); 37 memset(low,0,sizeof(low)); 38 memset(vs,0,sizeof(vs)); 39 flag=dfs_cut=0; 40 ans=sum; 41 } 42 43 void dfs(int u,int fa) 44 { 45 dfn[u]=low[u]=++dfs_cut; 46 vs[u]=1; 47 s.push(u); 48 int p=1; ///去重 49 for (int i=0;i<g[u].size();i++) 50 { 51 52 int v=g[u][i]; 53 if (v==fa&&p) 54 { 55 p=0; 56 continue; 57 } 58 if (!vs[v]) 59 { 60 dfs(v,u); 61 low[u]=min(low[u],low[v]); 62 if (low[v]>dfn[u]) ///判断桥 63 { 64 flag=1; 65 int temp=0,x; 66 67 ///给桥一遍压缩 68 while (1) 69 { 70 x=s.top(); 71 s.pop(); 72 temp+=a[x]; 73 if (x==v) break; 74 } 75 ans=min(ans,abs(sum-2*temp)); 76 a[u]+=temp; 77 } 78 79 } 80 else low[u]=min(low[u],dfn[v]); 81 } 82 } 83 84 int main() 85 { 86 int n,m; 87 while (~scanf("%d%d",&n,&m)) 88 { 89 Init(n); 90 while (m--) 91 { 92 int u,v; 93 scanf("%d%d",&u,&v); 94 g[u].push_back(v); 95 g[v].push_back(u); 96 } 97 dfs(0,-1); 98 if (flag) printf("%d\n",ans); 99 else printf("impossible\n"); 100 } 101 }