2-SAT 学习笔记
2-SAT 学习笔记
本文同载于本人的洛谷文章。
算法
2-SAT 用于解决什么样的问题?
问题
给定
例子
有 3 个集合:
解法
因为集合内不能同时选,所以集合内的两个元素我们互相取反。
把每个元素当成一个点,即把
现在我们连有向边,每条边
因为每个集合选一个元素,即不能同时选择。
所以对于条件
于是我们连好边了,然后求用
此时若
然后构造解,考虑按照拓扑序。
例如有
所以我们要按照拓扑序从大到小选择,但我们不用真的拓扑排序,我们求强连通分量时缩点的编号就是反着的拓扑序。
于是对于
有
模板题
注意这道题是"
其实就是
代码:
#include<bits/stdc++.h> using namespace std; int n,m; const int N=2e6+5; int stk[N],bz[N],dfn[N],low[N],num,dfn1,top; vector<int> g[N]; int neg(int x){ if(x<=n)return x+n; return x-n; } int nm[N]; void dfs(int x){ dfn[x]=low[x]=++dfn1,bz[x]=1,stk[++top]=x; for(int v:g[x]){ if(!dfn[v]) dfs(v),low[x]=min(low[v],low[x]); else if(bz[v]) low[x]=min(dfn[v],low[x]); } if(dfn[x]==low[x]){ ++num; while(stk[top]!=x)nm[stk[top]]=num,bz[stk[top]]=0,top--; nm[x]=num,bz[x]=0,top--; } } int ans[N]; int main(){ // freopen("2-sat.in","r",stdin); // freopen("2-sat.out","w",stdout); ios::sync_with_stdio(0); cin.tie(0); cin>>n>>m; for(int _i=1;_i<=m;_i++){ int i,a,j,b; cin>>i>>a>>j>>b; a^=1,b^=1; if(!a)i=neg(i); if(!b)j=neg(j); g[i].push_back(neg(j)); g[j].push_back(neg(i)); } for(int i=1;i<=2*n;i++){ if(!dfn[i])dfs(i); } for(int i=1;i<=n;i++){ if(nm[i]==nm[neg(i)]){ cout<<"IMPOSSIBLE"; return 0; } if(nm[i]<nm[neg(i)])ans[i]=1; } cout<<"POSSIBLE\n"; for(int i=1;i<=n;i++){ cout<<ans[i]<<" "; } }
本质思想
其实就是每个位置二选一,同时连边表示选了一个另一个必须选。
最后跑强连通分量求拓扑序,同时判断是否无解。
用这个思路可以应用在很多题目上。
注意:连边关系一定要列全,否则最后的答案可能不满足约束条件。
习题
jzoj 8097
P3209 [HNOI2010] 平面图判定
因为给出的环包括了
对于一条边,它可以在环内或环外,而它又不能与其他边相交。
这就是每个点选 0 或 1,同时有些边不能同时选 0 或 1,这可以用 2-SAT 来做。
我们重新标号,则对于
乍一看这个东西几乎不可做,直接做是
但是平面图有性质,即
于是对于不满足性质的直接判掉,此时
每条边分成两个点跑 2-SAT,由于
总时间
P3825 [NOI2017] 游戏
算法 1
如果
建边方式:
设题目所给条件为若
先看若
若
-
先连边
,即 选了后 必须选。 -
再连边
,即选 ,则不选 ,则 不能选,则选 。
判断有无解和构造方案与 2-SAT 板子一样。
期望得分 45 pts。
算法 2
我们可以
时间复杂度
期望得分 80 pts。
算法 3
考虑直接转化为对所有点的 2-SAT。
我们可以
时间复杂度
期望得分 80 pts。
算法 4
考虑改进算法 3。
对于每个
也就是每个
时间复杂度
期望得分 100 pts。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App