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 }
View Code

 

你可能感兴趣的:(tar)