题目描述
有n个布尔变量x1x xnx_1x~x_nx1x xn,另有m个需要满足的条件,每个条件的形式都是“xix_ixi为true/falsetrue/falsetrue/false或xjx_jxj为true/falsetrue/falsetrue/false”。比如“x1x_1x1为真或x3x_3x3为假”、“x7x_7x7为假或x2x_2x2为假
为假或x2x_2x2为假”。2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。
输入格式
第一行两个整数n和m,意义如体面所述。
接下来m行每行4个整数 iajbi a j biajb,表示“xix_ixi为aaa或xjx_jxj为bbb”(a,b∈{0,1})
输出格式
如无解,输出“IMPOSSIBLE”(不带引号); 否则输出"POSSIBLE"(不带引号),下 一行n个整数x1 xn,x∈0,1x_1~x_n,x∈{0,1}x1 xn,x∈0,1,表示构造出的解。
输入输出样例
输入 #1
3 1
1 1 3 0
输出 #1
POSSIBLE
0 0 0
说明/提示
1<=n,m<=1e61<=n,m<=1e^61<=n,m<=1e6
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <stack>
const int N = 2e6 + 62;
struct edge{
int to,next;
}e[N << 1];
static int head[N], cnt;
inline void addedge(int x, int y){ e[++cnt] = (edge){y, head[x]}, head[x] = cnt; }
static int dfn[N], low[N], vis[N], col[N], scnt, idx;
std::stack<int> st;
void dfs(int x){
dfn[x] = low[x] = ++idx, vis[x] = 1;
st.push(x);
for(int i = head[x]; i; i = e[i].next){
int nx = e[i].to;
if(!dfn[nx]){
dfs(nx);
low[x] = std::min(low[x], low[nx]);
}else if (vis[nx]) low[x] = std::min(low[x], dfn[nx]);
}
if(dfn[x] == low[x]){
for (scnt++; !st.empty();){
int _ = st.top();
st.pop(), vis[_] = 0, col[_] = scnt;
if (_ == x) break;
}
}
}
int n, m, x, a, y, b;
int main(){
register int i;
for(scanf("%d%d", &n, &m);m--;){
scanf("%d%d%d%d", &x, &a, &y, &b);
addedge(x + !a * n, y + b * n);
addedge(y + !b * n, x + a * n);
}
for(i = 1; i <= 2 * n; i++) if(!dfn[i]) dfs(i);
for(i = 1; i <= n; i++) if(col[i] == col[n + i]) return puts("IMPOSSIBLE"), 0;
puts("POSSIBLE");
for (i = 1; i <= n; i++) printf("%d ", col[i] > col[n + i]);
}