【笔记】2-SAT (tarjan)

TWO-SAT略解:

Part 1 (引入):

其实2-SAT是用来解决一系列类似如果我怎么怎么样,他就怎么怎么怎么样的东西,具体来说就是只有两种状态,两种状态不能兼得。

举个例子:

\(A\) 说如果 \(B\) 去参加群架,那我也得去。

\(B\) 说如果有群架,那我跟 \(C\) 去一个就可以了。

\(C\) 说如果有群架,那我肯定去。

发现这道题其实咱小学就会做了只要画个表格,填个表格就行了。

那考虑怎么让计算机快速的求出这个东西。

Part 2 (口糊):

还是以上面那个例子。

对于 \(A\) 说的话,咱可以这样连边: \(B->A\)

对于 \(B\) 说的话,咱这么连 \(B'->C,C'->B\)

对于 \(C\) 说的话,咱这么连 \(C'->C\)

(所有的'表示这个点不选)

然后考虑怎么做这个玩意儿。

我们可以对它跑一边tarjan求出所有强连通分量,然后按照拓扑序判断每个点选还是不选。

为什么是拓扑序呢?

考虑\(x->x'\),那么肯定如果 \(x\) 选了 \(x'\) 也得选,但是按照咱的说法,这条边的意思是:\(x\) 这个点一定不选。那就矛盾了,只能选拓扑序大的

这里说一下关于tarjan的小技巧,tarjan出来给出的就是反拓扑序,所以其实我们要找的是强连通分量编号小的。

Part 3 (代码):

inline bool two_sat(){
    for(int i=1;i<=n;++i)
        if(scc[i]==scc[i+n]) return false;
    return true;
}

尴尬,好短啊。。。

Part 4 (例题):

JSOI原题

发现这题其实是个垃圾题,每种材料只有两种做法,跑一遍裸的2-SAT

模板题

这题可一用来练输出方案。

CF875C:

这题是真的好题,乍一眼看不会,其实是2-SAT,可以参考这篇博文:

CR我都帮你安利了还不帮我推销推销

大概就这样了,最后一题博主的题解:(还没写,到时候补上。。。)

转载于:https://www.cnblogs.com/JCNL666/p/10765514.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值