2-SAT问题
2-SAT问题
2-SAT 问题,
简单来说,就是给出一个由 n 个布尔值组成的序列 A,再给出 m 个限制关系,每个条件的形式都是 Xi 为真/假 或 Xj 为真/假(比如:A[x] AND A[y]=0、A[x] OR A[y] OR A[z]=1 等),来确定 A[0..n-1] 的值,使得其满足所有限制关系,这样的问题就是 SAT 问题,特别的,若每种限制关系中最多只对两个元素进行限制,则称为 2-SAT 问题。
首先将给出的 n 个变量的每个变量 i 拆分成两个结点 i、i+n,分别表示第 i 个变量为真、第 i+n 个变量为假,这样就将 n 个点拆分成了 n 对。
- 对于一元关系:对于 Xi 为真,可以通过连边 <i+n,i> 实现,Xi 为假,可以通过连边 <i,i+n> 来实现。(该句略显抽象)
- 对于二元关系:以 “Xi 为假或者 Xj 为假“ 为例,其可以表述为:若 Xi 为真,则 Xj 为假,若 Xj 为真,则 Xi 为假,因此需要连两条边:<i,j+n>、<j,i+n>
但是,对于一组布尔方程,可能会有多组解同时成立。要怎样判断给每个布尔变量赋的值是否恰好构成一组解呢?
- 【x == false】if(x 可推出 !x) 之前跑tarjan时一定先给!x 染色,也就是说co[x] > co[!x],
- 【x == true】if(!x 可推出 x) 一定先给x染色 co[x] < co[!x]
- 【双解!】if (x ,!x 之间没有推导关系)随便给x赋值
- 【无解!】if (x 可相互推出 !x) x和!x在一个图层里,co[x] == co[!x]
注意:“可推出”指可间接推出,只要u有一条很长很长的路径到v就行,不一定是u到v有直接连边。
总结下来,当保证有解时,只需要把x赋值成(co[x] < co[!x])就是一种解