题目描述
有n个布尔变量 x 1 x x n x_1x~x_n x1x xn,另有m个需要满足的条件,每个条件的形式都是“ x i x_i xi为 t r u e / f a l s e true/false true/false或 x j x_j xj为 t r u e / f a l s e true/false true/false”。比如“ x 1 x_1 x1为真或 x 3 x_3 x3为假”、“ x 7 x_7 x7为假或 x 2 x_2 x2为假
为假或 x 2 x_2 x2为假”。2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。
输入格式
第一行两个整数n和m,意义如体面所述。
接下来m行每行4个整数 i a j b i a j b iajb,表示“ x i x_i xi为 a a a或 x j x_j xj为 b b b”(a,b∈{0,1})
输出格式
如无解,输出“IMPOSSIBLE”(不带引号); 否则输出"POSSIBLE"(不带引号),下 一行n个整数 x 1 x n , x ∈ 0 , 1 x_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 < = 1 e 6 1<=n,m<=1e^6 1<=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]);
}