zoukankan      html  css  js  c++  java
  • 2-SAT超入门讲解

    Preface

    说实话2-SAT的题目我都没怎么做过,所以这里讲的都是些超入门什么的

    还有一些板子题由于是暑假的时候学的所以有些我也记不清了

    主要学习参考自:Manchery的课件&&dalao's blog&&Another dalao


    What is 2_SAT?

    SAT是适定性(Satisfiability)问题的简称 。一般形式为k-适定性问题,简称 k-SAT。

    可以证明,当(k>2)时,k-SAT是NP完全的。因此一般讨论的是(k=2)的情况,即2-SAT问题。

    我们通俗的说,就是给你(n)个变量(a_i),每个变量能且只能(0/1)的值。同时给出若干条件,形式诸如((not)a_ioperatorname{opt}(not) a_j=0/1),其中(opt)表示(and,or,xor)中的一种

    而求解2-SAT的解就是求出满足所有限制的一组(a)


    Change 2-SAT into Graph Theory

    首先我们考虑将2-SAT问题往图论的方向靠,我们发现每个点要么取(0),要么取(1)。因此对于(a_i),我们建两个点(2i-1)(2i)分别表示(a_i)(0)(1)

    然后我们考虑建边来表示这些关系,我们令一条有向边的意义:(x o y)表示如果选择了(x)就必须选(y)

    那么我们可以举一些简单的例子来总结下连边的规律(用(i')表示(i)的反面):

    • (i,j)不能同时选:选了(i)就要选(j'),选(j)就要选(i')。故(i o j',j o i')。一般操作即为(a_i operatorname{xor} a_j=1)
    • (i,j)必须同时选:选了(i)就要选(j),选(j)就要选(i)。故(i o j,j o i)。一般操作即为(a_i operatorname{xor} a_j=0)
    • (i,j)任选(但至少选一个)选一个:选了(i)就要选(j'),选(j)就要选(i'),选(i')就要选(j),选(j')就要选(i)。故(i o j',j o i',i' o j,j' o i)。一般操作即为(a_i operatorname{or} a_j=1)
    • (i)必须选:直接(i' o i),可以保证无论怎样都选(i)。一般操作为给出的(a_i=1)(a_i operatorname{and} a_j=1)

    建好图然后就是考虑怎么用图论的方式解决2-SAT了。


    How to solve 2-SAT——DFS

    1. 对于每个当前不确定的变量(a_i),令(a_i=0)然后沿着边DFS访问相连的点。
    2. 检查如果会导致任意一个(j)(j')都被选,那么撤销。否则令(a_i=0)
    3. 否则令(a_i=1),重复2。如果还不行就无解。
    4. 继续考虑下一个不确定的变量

    这样的话正确性显然,由于这里的DFS涉及到全局,因此复杂度是(O(n(n+m)))的。

    一般情况下已经很优秀了,而且还可以改进:

    只需要在DFS之前判断(i')能否走到(i)就可以省略撤销标记的过程,所以我们可以bitset优化传递闭包做到(O(frac{n^3}{w}))预处理,然后就可以(O(n+m))的DFS了。

    这种做法还可以保证解的字典序,有时不失为一种不错的方法。


    How to solve 2-SAT——SCC

    考虑我们上面的判断有无解的情况,我们想到完全可以借助SCC来判断两个点是否互相到达。

    那么我们先缩点,如果(i)(i')在同一SCC里那么显然无解。

    否则选择(i)(i')拓扑序较大的一个就可以得到一组可行解。

    不是很常用(主要是一般题目的数据范围都不需要),用来判可行性比较好。


    两道例题

    HDU3062&&HDU1814 sol


    Postscript

    这真的是一篇超入门博客,没有涉及特别多的难点以及姿势。

    数据结构优化建图我是肯定不会的啦,最后推荐一道比较有难度的2-SAT好题:Luogu P3825 [NOI2017]游戏&&Sol

  • 相关阅读:
    机会的三种境界
    常用“快”捷键
    心路历程
    中兴笔试及答案
    浅谈oracle中row_number() over()分析函数用法
    IE的F12开发人员工具不显示问题
    1002.A + B Problem II --大数问题
    6470.count --快速矩阵幂
    4151.电影--贪心
    3070.斐波拉契数列--快速幂
  • 原文地址:https://www.cnblogs.com/cjjsb/p/9771868.html
Copyright © 2011-2022 走看看