• 2-SAT问题的算法


    2-SAT问题:有n个bool变量x1,x2....xn,还有一些必须满足的条件。这些条件列如“x1为假或x2为真”,即“x1假x2假”、“x1假x2真”、“x1真x2真”。

    求解2-SAT问题的算法有很多,有一种效率还不错,实现方便又理解方便的算法。

    注意例子中的那个条件“x1为假或x2为真”,在x1为假的时候x2可以为任意值,但在x1为真的时候,x2为满足条件必须是真。也就是说x1为真可以推导出x2为假、x2为假可以推导出x1为真。换成一般的情况,已知xa→xb',则xb→xa'、已知xa'→xb,则xb'→xa(xi表示真xi'表示假)这个称为对称性,仔细理解下,下面证明会用到这个结论。

    我们通常建一个图G,图中节点数量为2n,把节点标号,2i节点代表着xi、2i+1代表xi'。如果xi为真的时候标记节点2i,为假的时候标记2i+1。如果知道xa→xb',则加入一条有向边2a→2b+1,同时得到xb→xa',再加入一条边2b→2a+1。

    枚举2i和2i+1都没有标记的节点,先假设xi为真,给2i标记,再进行dfs遍历,把所有可以到达的点都标记,标记过程中如果出现某个点2x和2x+1都被标记,因为不会存在x同时为真和假的情况,所以xi不能为真。再假设x2为假,给2i+1标记重复上述过程。如果xi值为真和假时都不可以,则此题无解。

    修改之前的变量可以不可以让正在枚举的点可以为真或假?答案是不可以。因为假设某个节点a被标记,dfs时遍历到a'发现矛盾,则有条路可以从i走到a’,根据对称性,a有条路可以走到i,i就不是2i和2i+1都没有被标记的节点,矛盾,所以不存在这种情况。所以dfs遍历到的点要么是已经标记过的点或者2i和2i+1都未标记的点,与之前的变量无关,所以2-SAT算法正确


    伪代码:

    bool dfs(int x){

    ____如果x节点被标记,返回真

    ____如果x^1节点被标记,返回假

    ____u为x可以到达的所有节点

    ________如果dfs(u)为假,返回假

    ____返回真

    }

    bool solve(){

    ____for i=1 to n

    ________如果2i和2i+1都为标记

    ____________如果dfs(2i)为假

    ________________清除上次遍历的节点的标记 //实现时可以用栈

    ________________如果dfs(2i+1)为假,返回假

    ____返回真

    }

  • 相关阅读:
    os.path.basename()和os.path.splitext()
    关于pytorch中@和*的用处
    Python | os.path.join() method
    SURF (Speeded Up Robust Features,加速稳健特征)
    Canny算子
    医学影像中常见名词解释
    sigmod、tanh、ReLU激活函数的实现
    plt.gca()坐标轴移动
    损失函数和梯度下降解释
    torch和numpy的相互转换
  • 原文地址:https://www.cnblogs.com/Chenyao2333/p/3691885.html
Copyright © 2020-2023  润新知