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;
}
posted @ 2016-12-27 20:01  Krew  阅读(111)  评论(0)    收藏  举报