2-SAT裸题
如果选u则必选v', 如果选v则必选u',连边即可。
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
struct Edge{
int too, nxt;
}edge[40005];
int n, m, uu, vv, hea[16005], cnt, val, ans[16005], bel[16005];
void add_edge(int fro, int too){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
hea[fro] = cnt;
}
inline int f(int x){
return x%2==1?x+1:x-1;
}
bool pnt(int x){
if(bel[x]) return bel[x]==1;
bel[x] = 1;
bel[f(x)] = 2;
ans[++val] = x;
for(int i=hea[x]; i; i=edge[i].nxt)
if(!pnt(edge[i].too))
return false;
return true;
}
bool work(){
for(int i=1; i<=n+n; i++){
if(bel[i])
continue;
val = 0;
if(!pnt(i)){
for(int j=1; j<=val; j++)
bel[ans[j]] = bel[f(ans[j])] = 0;
if(!pnt(f(i))) return false;
}
}
return true;
}
int main(){
while(scanf("%d %d", &n, &m)!=EOF){
memset(hea, 0, sizeof(hea));
memset(bel, 0, sizeof(bel));
cnt = 0;
for(int i=1; i<=m; i++){
scanf("%d %d", &uu, &vv);
add_edge(uu, f(vv));
add_edge(vv, f(uu));
}
if(work()){
for(int i=1; i<=n+n; i++)
if(bel[i]==1)
printf("%d
", i);
}
else printf("NIE
");
}
return 0;
}