题意:给出n个点,m条边,找出一个子二分图,让这个子二分图的变数至少为m/2,题目保证一定存在这样的子二分图。
题目中给了二分图与子图的定义,二分图的定义是:如果一个图的所有顶点可以被分为U V两个集合,并且所有边的两个顶点恰好一个属于U,一个属于Y,即每个集合内的顶点没有边相连,那么此图就是二分图。二分图里并不含有奇圈。
这道题贪心的来做,假设前i个点已经形成了二分图,再添加第i+1个点的时候,判断第i+1个点与右边相连的点多还是与左边相连的点多,右边多就把此点划分为左边,左边多就把此点划分为右边。
#include <iostream>
#include <cstdio>
#include <vector>
#include <string.h>
using namespace std;
vector<int> l,r;
int color[105];
int edge[105][105];
int n,m;
int main(void){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
memset(edge,0,sizeof(edge));
memset(color,0,sizeof(color));
l.clear();
r.clear();
int x,y;
for(int i = 0; i < m; i++){
scanf("%d%d",&x,&y);
edge[x][y] = edge[y][x] = 1;
}
for(int i = 1; i <= n; i++){
int a = 0,b = 0;
for(int j = 1; j <= n; j++){
if(edge[i][j]){
if(color[j] == 1){
a++;
}
else{
b++;
}
}
}
if(a > b){
color[i] = 2;
l.push_back(i);
}
else{
color[i] = 1;
r.push_back(i);
}
}
int len1 = l.size(),len2 = r.size();
printf("%d ",len1);
for(int i = 0; i < len1; i++){
printf("%d ",l[i]);
}
printf("\n");
printf("%d ",len2);
for(int i = 0; i < len2; i++){
printf("%d ",r[i]);
}
printf("\n");
}
return 0;
}