给出一个无向图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.