无向图变成二分图

来源:互联网 发布:mac 远程看windows 编辑:程序博客网 时间:2024/06/05 16:45

给出一个无向图G,图上的点有权值。要求将G组织成一个二分图,使得同侧的点之间没有边相连,并且两侧点权总和之差最小。

转化为0-1背包问题。

#include<cstdio>#include<cstring>#include<string.h>#include<algorithm>#include<iostream>#include<math.h>#include<vector>#include<stack>using namespace std;const int offset=2010;const int maxdiff=offset*2+1;const int maxn=110;bool diff[2][maxdiff];int num[maxn][2];struct Node{int w;bool visited;}node[maxn];int n;int tot;char edge[maxn][maxn];void dfs(int root,int part){num[tot][part]+=node[root].w;node[root].visited=true;for(int i=0;i<n;i++){if(edge[root][i]=='1'&&!node[i].visited){dfs(i,1-part);}}}int main(){while(scanf("%d",&n)!=EOF){for(int i=0;i<n;i++){scanf("%d",&node[i].w);node[i].visited=false;}for(int i=0;i<n;i++){scanf("%s",edge[i]);}tot=0;memset(num,0,sizeof(num));for(int i=0;i<n;i++){if(!node[i].visited){dfs(i,0);tot++;}}int u=0,v=1;memset(diff[u],0,sizeof(diff[u]));diff[u][offset]=true;for(int i=0;i<tot;i++){memset(diff[v],0,sizeof(diff[v]));for(int j=0;j<maxdiff;j++){if(diff[u][j]){diff[v][j-num[i][0]+num[i][1]]=true;diff[v][j+num[i][0]-num[i][1]]=true;}}u=v,v=1-u;}int ans=offset;for(int i=0;i<maxdiff;i++){if(diff[u][i])ans=min(ans,abs(i-offset));}printf("%d\n",ans);}return 0;}

from sysuoj.