Sub-Bipartite Graph
Given a simple undirected graph G with n vertices and m edges, your task is to select a sub-bipartite graph of G with at least m/2 edges.
In the mathematical field of graph theory, a bipartite graph (or bigraph) is a graph whose vertices can be divided into two disjoint sets U and V such that every edge connects a vertex in U to one in V; that is, U and V are each independent sets. Equivalently, a bipartite graph is a graph that does not contain any odd-length cycles.
Equivalently, a bipartite graph is a graph that does not contain any odd-length cycles.
In the mathematical field of graph theory, a subgraph is a graph G whose graph vertices and graph edges form subsets of the graph vertices and graph edges of a given graph G..
In graph theory, a simple graph is a graph containing no self-loops or multiple edges.
from wikipedia
Input
The first line of the date is an integer T, which is the number of the text cases.
Then T cases follow, each case starts of two numbers N and M, representing the number of vertices and the number of edges, then M lines follow. Each line contains two integers x and y, means that there is an edge connected x and y. The number of nodes is from 1 to N.
1 <= T <= 100, 1 <= N <= 100, 0 <= M <= 10086
For each case, you should output two lines to describe your sub-graph, the first line is the set of U and the second line is the set of V.
Each line should output an integer F first, which is the total number of the vertices in this set, then F integers follow which are the number of each vertex of this part, see sample input and sample output for more details.
You can assume that the answer is always existed.
3 1 0 2 1 1 2 3 3 1 2 2 3 1 3Sample Output
1 1 0 1 1 1 2 2 1 2 1 3Hint
This problem is special judge.
题意:给定一个图,要求我们在这个图中构造一个二分图,且边数至少m/2
思路:贪心,用染色的方法,二分图嘛,就染成两种颜色,我们假设i个点都已经染好,并且是最优解那么第i+1个染色时我们遍历和i+1号点相连的所有点,让这个点染成和相连点不同的颜色看染哪种颜色的时候可以加的边最多,然后确定下这个点的颜色
最终遍历一边输出。
code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 111;
int n,m,cnt;
int head[maxn],color[maxn];
struct node{
int to;
int nex;
}edge[222*maxn];
void init(){
cnt = 0;
memset(head,-1,sizeof(head));
memset(color,-1,sizeof(color));
}
void add(int u,int v){
edge[cnt].to = v;
edge[cnt].nex = head[u];
head[u] = cnt++;
}
int main(){
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
init();
for(int i = 1; i <= m; i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
for(int i = 1; i <= n; i++){
int cnt0 = 0,cnt1 = 0;//cnt0表示i点染成0新加的边数,cnt1同理
for(int j = head[i]; j != -1; j = edge[j].nex){//遍历i点连接的点
int v = edge[j].to;
if(color[v] != 0) cnt0++;//如果与i连接的点不是0色,说明i点可以染成0色,所以边数加一
if(color[v] != 1) cnt1++;//同理
}
if(cnt0 > cnt1) color[i] = 0;//如果把i染成0色增加的边多,就染成0
else color[i] = 1;//反之
}
int cnt0 = 0,cnt1 = 0;
for(int i = 1; i <= n; i++){
if(color[i] == 1) cnt1++;
else cnt0++;
}
printf("%d",cnt0);
for(int i = 1; i <= n; i++){
if(color[i] == 0) printf(" %d",i);
}
printf("\n");
printf("%d",cnt1);
for(int i = 1; i <= n; i++){
if(color[i] == 1) printf(" %d",i);
}
printf("\n");
}
return 0;
}