hdu2242(树形dp+tarjan+缩点)
hdu2242 http://acm.hdu.edu.cn/showproblem.php?pid=2242
给定n,m表示n个点,m条边
每个点有个权值
问我们删除两某条边(割边)后将图分为两个部分,要使得两个部分的权值之差最小
这题的弱化版本是在一棵树上删除某条边后后将图分为两个部分,要使得两个部分的权值之差最小。是用树形dp来做的
但是这道题目是个图,但是我们可以转化为树,即将图中的边连通分量求出来,然后缩成一个点,建出一个新的树图,那么就可以用树形dp来求解题目了.
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <iostream> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <map> 10 #include <set> 11 #include <string> 12 #include <math.h> 13 using namespace std; 14 typedef long long LL; 15 const int INF = 1<<30; 16 const int N = 10000 + 10; 17 vector<int> g1[N],g2[N]; 18 int val1[N],val2[N]; 19 int dfn[N],low[N],dfs_clock,cnt; 20 int belong[N]; 21 stack<int> st; 22 bool vis[N]; 23 int ans,sum; 24 void tarjan(int u, int fa) 25 { 26 bool flag = false; 27 vis[u] = true; 28 dfn[u] = low[u] = ++dfs_clock; 29 st.push(u); 30 for(int i=0; i<g1[u].size(); ++i) 31 { 32 33 int v = g1[u][i]; 34 if(v==fa && !flag) 35 { 36 flag = true; 37 continue; 38 } 39 if(!vis[v]) tarjan(v,u); 40 low[u] = min(low[u],low[v]); 41 } 42 if(dfn[u]==low[u]) 43 { 44 cnt++; 45 int x; 46 do 47 { 48 x= st.top(); 49 st.pop(); 50 belong[x] = cnt; 51 val2[cnt] += val1[x]; 52 }while(u!=x); 53 } 54 } 55 56 void dfs(int u, int fa) 57 { 58 vis[u] = true; 59 for(int i=0; i<g2[u].size(); ++i) 60 { 61 int v = g2[u][i]; 62 if(vis[v]) continue; 63 dfs(v,u); 64 val2[u] += val2[v]; 65 } 66 } 67 void dfs2(int u, int fa) 68 { 69 vis[u] = true; 70 for(int i=0; i<g2[u].size(); ++i) 71 { 72 int v = g2[u][i]; 73 if(vis[v]) continue; 74 ans = min(ans,abs(sum-2*val2[v])); 75 dfs2(v,u); 76 } 77 } 78 int main() 79 { 80 int n,m,i,u,v,j; 81 while(scanf("%d%d",&n,&m)!=EOF) 82 { 83 for(i=0; i<=n; ++i) 84 { 85 g1[i].clear(); 86 g2[i].clear(); 87 } 88 sum = 0; 89 for(i=0; i<n; ++i) 90 { 91 scanf("%d",&val1[i]); 92 sum += val1[i]; 93 } 94 for(i=0; i<m; ++i) 95 { 96 scanf("%d%d",&u,&v); 97 g1[u].push_back(v); 98 g1[v].push_back(u); 99 } 100 memset(vis,0,sizeof(vis)); 101 memset(dfn,0,sizeof(dfn)); 102 memset(low,0,sizeof(low)); 103 memset(val2,0,sizeof(val2)); 104 dfs_clock = 0; 105 cnt = 0; 106 tarjan(0,-1); 107 for(i=0; i<n; ++i) 108 for(j=0; j<g1[i].size(); ++j) 109 { 110 int v = g1[i][j]; 111 if(belong[v] != belong[i])//建新图,虽然新建的图会有重边,但是不影响树形dp 112 { 113 g2[belong[i]].push_back(belong[v]); 114 g2[belong[v]].push_back(belong[i]); 115 } 116 } 117 if(cnt==1)//如果整个图是边连通的,那么不管删哪条边都不能使得图不连通 118 { 119 puts("impossible"); 120 continue; 121 } 122 ans = INF; 123 memset(vis,0,sizeof(vis)); 124 dfs(1,-1); 125 memset(vis,0,sizeof(vis)); 126 dfs2(1,-1); 127 printf("%d\n",ans); 128 } 129 return 0; 130 }