2-SAT
2-SAT
2-SAT指的是这样一类问题:给出\(n\)个布尔变量和\(m\)个限制,形如:$$x_i为真/假 或 x_j为真/假$$
求满足所有条件的一组布尔值。
我们可以把它转化为一个图上的关系,设结点\(2x_i\)表示\(x_i\)为假,\(2x_i+1\)表示\(x_i\)为真
以关系\(x_i 为真 或 x_j 为假\)举例,如果\(x_i\)为假,那么\(x_j\)就只能是假,反之若\(x_j\)为真,那么\(x_i\)必为真,所以我们可以连接两条有向边:$$(2x_i ->2x_j) (2x_i+1 ->2x_j+1)$$
对于其他形式的条件同理,在建完图后依次考虑未赋值的变量,分别在每个选择上DFS看是否存在矛盾(如果两者都有矛盾,那么2-SAT无解),总的时间复杂度为\(O(n+m)\)
代码:
void relate(int x,int sx,int y,int sy) //sx,sy为0表示假,1表示真
{
G[(x<<1)|sx].push_back((y<<1)|(1^sy));
G[(y<<1)|sy].push_back((x<<1)|(1^sx));
}
bool DFS(int k)
{
if (T[k^1]) return false; //矛盾
if (T[k]) return true; //满足条件
T[k]=true;
rep(i,0,sz(G[k])-1) if (!DFS(G[k][i])) {T[k]=false;return false;}
return true;
}
bool solve()
{
rep(i,1,n)
if ((!T[(i<<1)])&&(!T[(i<<1)|1])) //还未赋值
if ((!DFS(i<<1))&&(!DFS((i<<1)|1))) return false; //无解
return true;
}

浙公网安备 33010602011771号