2-SAT
我 注定摒除 所有怅惘
执 着缔造 无暇开场我 注定离开 这个地方
动身往云间翱翔我 生为飞蛾 天性向光
撕裂疮疤 复苏生长我 生为凤凰 本能高唱
倔强是翅膀
——洛天依《向光》
2-SAT
算法本身很简单,难点在于建模。
所以本质上就是构造。
核心的方案就是把 \(p \lor q\) 转化为 \(\neg p \to q\),\(\neg q \to p\) 这两条边,其它条件基本上都可以转化为若干个 \(p \lor q\) 的 \(\land\) 的形式。
例如 \(p\) 成立等价于 \(p \lor p\) 可转化为 \(\neg p \to p\)。
天依宝宝可爱!
洛谷 P4782
思维难度:\(\color{#FE4C61} 红\) *800
板子题。
先把每个命题拆成 \(p\) 和 \(\neg p\),于是条件可以表示成若干个 \(p \Rarr q\) 的形式,于是这么建图。
显然如果 \(p\) 和 \(\neg p\) 在同一个 scc 内,那么一定无解。
那么 tarjan 缩点求出拓扑序,于是在得到的 DAG 中如果前面的点为真,呢么这个点后面的所有点一定都为真。又因为 \(p\) 与 \(\neg p\) 不能同时成立,所以总是让这两者中靠后的那个为真,靠前的那个为假一定是更优的。
可以证明这样做一定可以构造出一组合法解,看起来好像不大对,但确实是对的,虽然我不会证吧(
还有,实际上不需要显式地求出拓扑序,因为据说 tarjan 缩点后的 scc 编号就是反向的拓扑序。
注意连边的时候如果连了一条边 \(p \to q\),那么也一定要连 \(\neg q \to \neg p\)。
天依宝宝可爱!
洛谷 P5782
思维难度:\(\color{#FE4C61} 红\) *800
为什么要放两道一模一样的板子题()
天依宝宝可爱!
洛谷 P4171
思维难度:\(\color{#FE4C61} 红\) *800
为什么要放三道一模一样的板子题()
天依宝宝可爱!
洛谷 P6378
思维难度:\(\color{#FFC116} 黄\) *1500
终于不是板子题了。
显然可以暴力建图。具体地,对于原图上每条边 \(u,v\) 满足的条件是 \(u \lor v\),这个是容易的;对于一个部分 \(s\) 的所有点 \(u\),都这样建边:\(\forall _{v \in s \land v \ne u} u \to v\) 即可。
但是这样边数是 \(O(n^2)\) 的,显然不可行(不过还是可以得到 92pts 的好成绩!
然后有一个挺神的 trick,就是前缀优化建图。
现在只考虑同一部分内的点。我们新建一些点,\(p_i\) 表示 \(a_{1 \sim i}\) 中是否有关键点。于是就得到了这样的图:
然后考虑建哪些边:
- 首先根据 \(p\) 的定义,\(a_i \to p_i\) 这条边一定是要建的;同时对应的 \(\neg p_i \to \neg a_i\) 也要建。
- 然后因为是前缀,\(p_i \to p_{i+1}\) 也要建;对应 \(\neg p_{i+1} \to \neg p_i\)。
- 因为只能选一个关键点的限制,所以 \(p_i \to \neg a_{i+1}\) 也要建;对应 \(a_{i+1} \to \neg p_i\)。
得到这样一个图:
总边数为 \(2 \times (3n+m) \le 8 \times 10^6\)。
在 \(p\) 的建立上,有一个简便方法,可以直接拿 \(p_{a_i}\) 表示 \(a_i\) 对应的前缀,这样就不需要分别算每个部分的 \(p\) 了。
感觉有时间要补一补图论建模,不过等后面吧,毕竟写 ds 已经写吐了……
天依宝宝可爱!
CF568C
思维难度:\(\color{#52C41A} 绿\) *1700
思路还是比较简单的。就直接从前往后贪心,尽量让靠前的位置和给定串相同,后面尽量往小了放就可以。因为数据范围太小,所以即使每次 \(O(m)\) 跑一遍 2-SAT,总复杂度也是 \(O(nm)\) 的。
不过细节巨巨巨巨巨多。
所以放弃了,扔一个光荣的 Wrong answer on test 1 在这里吧 😃 submission
天依宝宝可爱!



浙公网安备 33010602011771号