题意:给出N个点M条边的图,现在要从中选出两个不相交的点集,使得以这两个点集构成的原图的子图构成一个二分图,并使得边数>=M/2。
思路:一个一个点去染色,对于当前点,判断染哪个颜色使得受益最大就染哪个颜色,
参考http://blog.csdn.net/qian99/article/details/22994069
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn = 100 + 10;
#define INF 0x3f3f3f3f
#define Inf 0x3FFFFFFFFFFFFFFFLL
#define clr(x,y) memset(x,y,sizeof x)
int n,m;
int maze[maxn][maxn];
int col[maxn];
int U,V;
void calc(int x)
{
int u = 0,v =0;
for(int i = 1; i <= n; i ++)
if(maze[i][x])
{
if(col[i] != 1)
u ++;
if(col[i] != 2)
v ++;
}
if(u >= v)
col[x] = 1,U ++;
else col[x] = 2,V ++;
}
int main()
{
int Tcase;
scanf("%d",&Tcase);
while(Tcase --)
{
U = 0,V = 0;
clr(maze,0);
clr(col,0);
scanf("%d%d",&n,&m);
for(int i = 1; i <= m; i ++)
{
int x,y;
scanf("%d%d",&x,&y);
maze[x][y] = 1;
}
for(int i = 1; i <= n; i ++)
calc(i);
cout << U;
for(int i = 1; i <= n; i ++)
if(col[i] == 1)
cout << " " << i ;
cout << endl;
cout << V;
for(int i = 1; i <= n; i ++)
if(col[i] == 2)
cout << " " << i ;
cout << endl;
}
return 0;
}