思路:
因为要解决最小最小字典序的问题,所以经典的2-SAT解决方法就没用了。。。只能暴力dfs。。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string.h>
#include <queue>
using namespace std;
const int maxn = 8010*2;
struct edge{
int to,v,next;
}ed[maxn*4];
int head[maxn],cnte = 0;
void ae(int x,int y){//addedge
ed[++cnte].to = y;
ed[cnte].next=head[x];
head[x]=cnte;
}
int n,m;
int col[maxn];
int pre[maxn];int cntp = 0;
//判断x点能不能选 因为x点能不能选需要选后边的点来试。。
bool dfs(int x){
if(col[x]==1) return true;
if(col[x^1]==1) return false;
col[x]=1,col[x^1]=-1;
pre[cntp++]=x;
for(int i=head[x];i!=-1;i=ed[i].next){
int to = ed[i].to;
if(!dfs(to)){
return false;
}
}
return true;
}
bool solve(){
for(int i = 0;i < 2*n;i+=2){
cntp = 0;
if(!dfs(i)){//如果第一个点选不了
for(int j=0;j<cntp;j++){
col[pre[j]] = col[pre[j]^1] = 0;
}
if(!dfs(i+1)){//如果第二个点也选不了 无解
return false;
}
}
else{//选第一个点
col[i]=1,col[i^1]=-1;
}
}
return true;
}
int main(){
int flag = 0,a,b;
while(~scanf("%d%d",&n,&m)){
memset(head,-1,sizeof(head));
memset(col,0,sizeof(col));
cntp = 0,flag=0,cnte=0;
for(int i = 1;i <= m;i++){
scanf("%d%d",&a,&b);a--,b--;
ae(a,b^1);ae(b,a^1);
}
flag = solve();
for(int i = 0;i < 2*n && flag == 1;i++){
if(col[i]==1){
printf("%d\n",i+1);
}
}
if(flag == 0) printf("NIE\n");
}
return 0;
}