给定一个布尔方程,判断是否存在一组布尔变量的真值指派使整个方程为真的问题,被称为布尔方程的可满足性问题(SAT)。如果合取范式的每个子句中的文字个数都不超过两个,那么对应的SAT问题又称为2-SAT问题。(具体例子看代码)
利用强连通分量分解点击打开链接,可以在布尔公式子句数的线性时间内解决2-SAT问题。首先,把每个子句(a∨b)改写成等价形式(¬a=>b∧¬b=>a),这样就把原布尔公式以=>关系为边建立有向图。此时,显然该图中同一个强连通分量所含布尔值均相同。如果存在某个布尔变量x,¬x均在同一个强连通分量中,则显然无法令整个布尔公式的值为真。反之,如果不存在这样的布尔变量,那么对于每个布尔变量x,x所在的强连通分量的拓扑序在¬x所在的强连通分量之后<=>x为真。
代码:
int main()
{
//布尔公式为(a∨¬b)∧(b∨c)∧(¬c∨¬a)时
//构造6个顶点,分别对应a,b,c,¬a,¬b,¬c
V=6;
//a∨¬b转成¬a=>b∧b=>a
add_edge(3,4);//从¬a连一条到¬b的边
add_edge(1,0);//从b连一条到a的边
//同上
add_edge(4,2);//略
add_edge(5,1);//略
//同上
add_edge(2,3);//略
add_edge(0,5);//略
//进行强连通分量分解
scc();
//判断是否可满足
for(int i=0;i<3;i++)
{
if(cmp[i]==cmp[3+i])
{
printf("NO");
return 0;
}
}
//如果可满足,则给出一组解
printf("YES\n");
for(int i=0;i<3;i++)
if(cmp[i]>cmp[3+i])
printf("true\n");
else
printf("false\n");
return 0;
}