hdu 2242(边双连通分量)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2242

思路:Tarjan求边双连通分量,进行缩点后成树,然后就是树型dp,求一下最小差值就行了。

ps:注意点:由于双向建边,DP搜索时要记录父亲,只能往下搜,不能搜该节点的父亲。

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stack>

 6 #include<vector>

 7 using namespace std;

 8 #define MAXN 10000+10

 9 #define inf 1<<30

10 stack<int>S;

11 vector<int>vet[MAXN];

12 vector<int>map[MAXN];

13 int n,m,cnt,_count,sum,MIN;

14 int dfn[MAXN],low[MAXN];

15 bool mark[MAXN];

16 int color[MAXN];

17 int dp[MAXN];

18 int value[MAXN];

19 

20 //tarjan算法找边双联通分量并进行缩点

21 void Tarjan(int u,int father){

22    int flag=0;

23    dfn[u]=low[u]=++cnt;

24    mark[u]=true;

25    S.push(u);

26    for(int i=0;i<vet[u].size();i++){

27       int v=vet[u][i];

28       if(v==father&&!flag){ flag=1;continue; }//考虑重边情况,重要

29       if(!mark[v])Tarjan(v,u);

30       low[u]=min(low[u],low[v]);

31    }

32    if(low[u]==dfn[u]){

33       _count++;

34       int v;

35       do{

36          v=S.top();

37          S.pop();

38          color[v]=_count;//染色

39          dp[_count]+=value[v];//求缩点后的价值

40       }while(u!=v);

41    }

42 }

43 

44 //树型dp求最小差值

45 int dfs(int u,int father){

46    int ans=dp[u];

47    for(int i=0;i<map[u].size();i++){

48       int v=map[u][i];

49       if(v==father)continue;

50       ans+=dfs(v,u);

51    }

52    MIN=min(MIN,abs((sum-ans)-ans));

53    return ans;

54 }

55 

56 

57 

58 int main(){

59 //   freopen("1.txt","r",stdin);

60    int u,v;

61    while(~scanf("%d%d",&n,&m)){

62       sum=cnt=_count=0;MIN=inf;

63       for(int i=0;i<=n;i++){ vet[i].clear();map[i].clear(); }

64       for(int i=0;i<n;i++){ scanf("%d",&value[i]);sum+=value[i]; }

65       while(m--){

66          scanf("%d%d",&u,&v);

67          vet[u].push_back(v);

68          vet[v].push_back(u);

69       }

70       memset(color,0,sizeof(color));

71       memset(dfn,0,sizeof(dfn));

72       memset(low,0,sizeof(low));

73       memset(mark,false,sizeof(mark));

74       memset(dp,0,sizeof(dp));

75       Tarjan(0,0);

76       if(_count==1){ puts("impossible");continue; }

77       for(int i=0;i<n;i++){

78          for(int j=0;j<vet[i].size();j++){

79             if(color[i]!=color[vet[i][j]]){

80                map[color[i]].push_back(color[vet[i][j]]);

81             }

82          }

83       }

84       dfs(1,0);

85       printf("%d\n",MIN);

86    }

87    return 0;

88 }
View Code

 

 

你可能感兴趣的:(HDU)