hdu 1814(2sat)
题意: 有n个组织,每个组织有两个人,第i组的两个人分别是2*i-1,2*i,其中有m对人相互讨厌,要在n个组织中各选一个人,使得没有任何两个人相互讨厌,如果存在答案,输出字典序最小的,如果无解,输出NIE
分析:如果i和j相互讨厌,那么那么如果选i,那么必定选j^1,选i^1必定选j,加入这两条边,跑2sat,字典序,用从小到大枚举来保证,如果找到一个解,立刻退出
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
struct sat{
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 xval,int y,int yval){
x=x*2+xval;
y=y*2+yval;
G[x^1].push_back(y);
G[y^1].push_back(x);
}
void add(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;
}
}Sat;
int main(){
int n,m;
while(cin>>n>>m){
Sat.init(n);
for(int i=0;i<m;i++){
int a,b;
cin>>a>>b;
a--;b--;
//a=a>>1;b=b>>1;
//Sat.add_clause(a,(a&1),b,(b&1));
Sat.add(a,b);
}
if(Sat.solve()){
for(int i=0;i<2*n;i+=2)
if(Sat.mark[i])
cout<<i+1<<endl;
else
cout<<i+2<<endl;
}
else puts("NIE");
}
return 0;
}

浙公网安备 33010602011771号