题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1814
题意: 有(1,2),(3,4), ...(2n-1,2n),n对数,要在每对中选出一个共n个,并且满足m个约束条件,条件(a,b)表示ab不能同时被选,按字典序输出答案,无解输出NIE
分析: Two_Sat问题,假设A,A‘为一对,B,B'为一对,那么对于约束条件(A,B),在选A的时候必须选B’,选B的时候必选选A‘,加边A->B',B->A'
模板用的是大白书上的,跑出来直接是字典序,mark为true即为取当前值。
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<vector>
#define maxn 8005
using namespace std;
struct TwoSAT{
int n;
vector<int> G[maxn*2];
bool mark[maxn*2];
int S[maxn*2],c;
bool dfs(int x){
if(mark[x^1])return false;
if(mark[x])
return true;
mark[x]=true;
S[c++]=x;
for(int i=0;i<G[x].size();i++)
if(!dfs(G[x][i]))return false;
return true;
}
void init(int n){
this->n=n;
for(int i=0;i<n*2;i++)
G[i].clear();
memset(mark,0,sizeof(mark));
}
void add_clause(int x,int y){
G[x].push_back(y^1);
G[y].push_back(x^1);
}
bool solve(){
for(int i=0;i<n*2;i+=2)
if(!mark[i]&&!mark[i+1]){
c=0;
if(!dfs(i)){
while(c>0)mark[S[--c]]=false;
if(!dfs(i+1))return false;
}
}
return true;
}
void print(){
if(!solve())
printf("NIE\n");
else {
for(int i=0;i<n;i++){
if(mark[i*2])
printf("%d\n",i*2+1);
else
printf("%d\n",i*2+2);
}
}
}
};
int main()
{
int n,m,x,y;
while(~scanf("%d%d",&n,&m)){
TwoSAT T;
T.init(n);
while(m--){
scanf("%d%d",&x,&y);
T.add_clause(x-1,y-1);
}
T.print();
}
return 0;
}