2-SAT问题
2-SAT问题
有 true
/ false
或 true
/ false
」。比如 「
2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。
求出构造出来的解(若无解输出POSSIBLE
)
输入格式
第一行两个整数
接下来
输出格式
如无解,输出 IMPOSSIBLE
;否则输出 POSSIBLE
。
下一行
样例 #1
样例输入 #1
3 1
1 1 3 0
样例输出 #1
POSSIBLE
0 0 0
解法
我们考虑建图,把 false
设成 true
设成
假如一个条件中可以建成一些边:
例如条件a 0 b 0
就代表要么a = false
要么b = false
那么很容易可以知道
如果 a = true 那么一定有 b = false
如果 b = true 那么一定有 a = false
a = true
b = false
我们就建一条边由
这条边就代表选择
无解的情况:
某一个变量的 false 能走到 true,从 true 也能走到 false,就说明无解。
为什么一个变量的 false(true) 能走到一个变量的 true(false) 不是无解的情况呢?
我们考虑边的意义:
选了这个变量的 false 就必须选这个变量的 true
那就选这个变量的 true不就好了!
这也是我们如何找出解的方法:
找出解
我们把每个点的 false 都 dfs 一次,
如果找不到这个点的 true,那就代表这个点可以选 false,
若找到了这个点的 true,则再在 true 上dfs一次,
如果 dfs 找不到 false,则代表这个点选true,
如果也 dfs 到了 false,那就证明无解。
这样的复杂度是
那怎么办呢?
我们考虑
tarjan缩点
某一个变量的 false 能走到 true,从 true 也能走到 false,就说明无解。
这就说明一个变量的 false 与 true 在一个强连通分量里面
tarjan 可以很好解决这个问题
for(int i = 1;i <= n; ++i){
if(c[i] == c[i + n]){
return 0;
}
}
那怎么找出解呢?
我们考虑
情况1:当一个点的 false 与 true 不会互相到达(指向),那就可以随便取
情况2:当一个点的 false 可以到达(指向) true,那就只能取 true
情况3:当一个点的 true 可以到达(指向) false,那就只能取 false
相互可以到达(就上面说的情况)就无解。
我们首先判断出来这有没有解,如果有解,那么情况二和情况三不可能都满足
我们现在所需要看的就是到底满足哪一个情况?
首先因为没有false和true是同一个强联通分量,所以
当一个点的 false 可以到达(指向) true,那么这个点的 false 在tarjan(dfs)里面必定被先找到,c[false] 也就比 c[true] 更大
当一个点的 true 可以到达(指向) false,那么这个点的 true 在tarjan(dfs)里面必定被先找到,c[true] 也就比 c[false] 更大
当两个点没关系的时候,可以随便取
for(int i = 1;i <= n; ++i){
if(c[i] > c[i + n]) printf("1 ");
else printf("0 ");
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具