题目链接
题目大意
现在有一个图G,n个点,m个边,求出两个不相交的子集,使得,每个子集都是一个顶点覆盖集,也就是每个边有一个顶点在这个集合里。
解题思路
一条边连接两个顶点,要这两个顶点的其中一个在其中集合中,也就是二分图,用染色法判断一下能不能组成二分图,相同颜色的是一个集合就可以啦。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
const int N=1e5+5;
int n,m,tot;
int f[N],col[N],a[N],b[N];
struct node
{
int v,nex;
};
node e[N*2];
void add(int u,int v)
{
e[tot].v=v;
e[tot].nex=f[u];
f[u]=tot++;
}
int dfs(int s)
{
queue<int>p;
p.push(s);
col[s]=1;
while(!p.empty())
{
int from=p.front();
p.pop();
for(int i=f[from];i!=-1;i=e[i].nex)
{
int v=e[i].v;
if(col[v]==-1)
{
p.push(v);
col[v]=!col[from];
}
if(col[from]==col[v])
return 0;
}
}
return 1;
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
memset(f,-1,sizeof(f));
memset(col,-1,sizeof(col));
int x,y;
for(int i=1;i<=m;i++)
{
scanf("%d %d",&x,&y);
add(x,y);
add(y,x);
}
int flag=0;
for(int i=1;i<=n;i++)
{
if(col[i]&&!dfs(i))
{
flag=1;
break;
}
}
if(flag)
printf("-1\n");
else
{
int ans1=0,ans2=0;
for(int i=1;i<=n;i++)
{
if(col[i]==1)
a[ans1++]=i;
else
b[ans2++]=i;
}
printf("%d\n",ans1);
for(int i=0;i<ans1;i++)
printf("%d ",a[i]);
printf("\n");
printf("%d\n",ans2);
for(int i=0;i<ans2;i++)
printf("%d ",b[i]);
printf("\n");
}
}
return 0;
}