description
有n个人,编号为1~n,告诉你哪些人之间是不友好的。现在,让你将这n个人分成两组,使得每一组之内的人是互相友好的,如果可以分成两组,则输出如何分组的,如果不可以分成两组,那么,输出“IMPOSSIBLE”。
input
第一行两个整数n和m(1<=n<=50,000,0<=m<=500,000),分别表示人数以及不友好的人的对数。以下m行每行两个数a和b,表示a与b是不友好的。
output
如果可以分成两个组,则输出一个方案,第一行为第一组的人的编号,第二行为第二组人的,按升序输出。
若有多组方案,取第一组人数最多的方案。在第一组人数最多的情况下,取字典序最小的方案。其中字典序最小指两组数字拼起来后的序列字典序最小。
如果不能分成两组,输出“IMPOSSIBLE”。
sample
input
5 4
1 4
1 5
2 4
2 5
output
1 2 3
4 5
solution
显然若存在奇环,则无解
要求字典序最小,则优先选小的放在集合1
从小到大枚举,若没被遍历过则放入集合1
接着 d f s dfs dfs,将所有与其相连的放入相反的集合
遂解
code
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define N 1000005
#define inf 1000000007
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fd(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
int n,m,tot,ans[N],dis[N];
bool bz[N],tag;
struct edge{
int nxt,to,st;
}t[N*2];
int read(){
int res=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-'&&((ch=getchar())>='0'&&(ch)<='9')) f=-1;
else ch=getchar();
}
while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();
return res*f;
}
void add(int u,int v){
t[++tot].nxt=t[u].st;t[tot].to=v,t[u].st=tot;
}
void dfs(int x,int fa){
bz[x]=1;
for(int i=t[x].st;i;i=t[i].nxt){
int v=t[i].to;
if(v==fa)continue;
if(bz[v]&&(dis[x]+1-dis[v])&1){
tag=1;
return;
}
if(bz[v])continue;
dis[v]=dis[x]+1;
dfs(v,x);
if(tag)return;
}
}
void solve(int x){
for(int i=t[x].st;i;i=t[i].nxt){
int v=t[i].to;
if(ans[v]!=-1)continue;
ans[v]=ans[x]^1;
solve(v);
}
}
int main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n=read(),m=read();
fo(i,1,m){
int u=read(),v=read();
add(u,v),add(v,u);
}
fo(i,1,n){
if(!bz[i])dfs(i,0);
}
if(tag){
puts("IMPOSSIBLE");
return 0;
}
fo(i,1,n)ans[i]=-1;
fo(i,1,n){
if(ans[i]==-1)ans[i]=0;
solve(i);
}
fo(i,1,n)if(ans[i]==0)printf("%d ",i);
puts("");
fo(i,1,n)if(ans[i]==1)printf("%d ",i);
}