[模板] 2-SAT 问题
简介
2-SAT (2-satisfiability) 问题形如:
- 给定一些变量 \(x_i \in \{true, false\}\);
- 给定一些一元/二元约束条件, 如 \(x_i \land \lnot x_j\), 利用 \(\land\) 连接;
- 为每一个变量赋一个值, 满足所有约束条件.
将第2条中的一/二元约束条件改为多元, 即为 N-SAT 问题.
可以证明 N-SAT 问题没有多项式解法, 但 2-SAT 问题有 \(O(n + m)\) 的解法.
算法
对每个变量建立两个点: \(x_i\), \(x_i'\), 表示取真或假.
根据约束条件建立若干条边 \((p, q)\), 表示若选 \(p\) 则必须选 \(q\). (见下)
将得到的图缩点. 若 \(x_i\) 和 \(x_i'\) 在同一个强连通分量内, 则无解.
否则, 若 \(x_i\) 的所在强连通分量的拓扑序大于 \(x_i'\), 则选 \(x_i\); 否则选 \(x_i'\).
我们知道tarjan算法求出的强连通分量标号为强连通分量拓扑序的逆序. 因此判断 \(scc_{x_i} < scc_{x_i'}\) 即可.
建边
- 一元逻辑
- \(p\): \((p', p)\);
- \(\lnot p\): \((p, p')\).
- 二元逻辑 (\(p\) 和 \(\lnot p\) 是一样的, 下面仅描述 \(p\) 的情况)
- \(p \rightarrow q\): \((p, q)\), \((q', p')\);
- \(p \land q\): 等价于 \(p\), \(q\);
- \(p \lor q\): \((p', q)\), \((q', p)\) (等价于 \(\lnot p \rightarrow q\));
- \(p \oplus q\): \((p, q')\), \((p', q)\), \((q, p')\), \((q', p)\). (xor)
容易发现所有二元逻辑都会建立若干对边, 这称作2-SAT问题的对称性, 是算法正确的关键.
较慢的算法 && 字典序最小解
我们还可以枚举每个点, 然后假设其为 true (或者 false), 从该点dfs判断是否可行.
这样可以求出一些特殊条件的解, 如最小字典序.
时间复杂度 \(O(nm)\), 但是多数情况跑不满.
代码
//任意解
int chos[nsz];
int dfn[nsz*2],pd=0,low[nsz*2],inscc[nsz*2],ps=0;
int stk[nsz*2],top=0,vi[nsz*2];
void tarj(int p){
dfn[p]=low[p]=++pd;
stk[++top]=p,vi[p]=1;
for(auto v:edge[p]){
if(dfn[v]==0){
tarj(v);
low[p]=min(low[p],low[v]);
}
else if(vi[v])low[p]=min(low[p],dfn[v]);
}
if(low[p]==dfn[p]){//scc
++ps;
int v;
do{
v=stk[top];
inscc[v]=ps,vi[v]=0,--top;
}while(v!=p);
}
}
bool sat2(){//toefl ielts sat
rep(i,2,n*2+1)if(dfn[i]==0)tarj(i);
rep(i,1,n){
if(inscc[i<<1]==inscc[i<<1|1])return 0;//no solution
chos[i]=inscc[i<<1|1]<inscc[i<<1];
}
return 1;
}
[模板] 2-SAT 问题的更多相关文章
- 2 - sat 模板(自用)
2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一 POJ 3207 Ikki's Story IV ...
- TwoSAT算法模板
该模板来自大白书 [解释] 给多个语句,每个语句为“ Xi为真(假) 或者 Xj为真(假)” 每个变量和拆成两个点 2*i为假, 2*i+1为真 “Xi为真 或 Xj为真” 等价于 “Xi为假 –& ...
- C++ 模板基础
我们学习使用C++,肯定都要了解模板这个概念.就我自己的理解,模板其实就是为复用而生,模板就是实现代码复用机制的一种工具,它可以实现类型参数化,即把类型定义为参数:进而实现了真正的代码可重用性.模版可 ...
- (模板)poj2947(高斯消元法解同余方程组)
题目链接:https://vjudge.net/problem/POJ-2947 题意:转换题意后就是已知m个同余方程,求n个变量. 思路: 值得学习的是这个模板里消元用到lcm的那一块.注意题目输出 ...
- 虚拟化技术之kvm镜像模板制作工具virt-sysprep
virt-sysprep这个工具来自libguest-tools这个工具包,它能够把kvm虚拟机对应的磁盘文件做成一个模板,后续我们启动虚拟机就可以基于这个镜像模板启动:什么是镜像模板呢?所谓模板就是 ...
- Jade模板引擎让你飞
写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...
- ABP入门系列(2)——通过模板创建MAP版本项目
一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...
- CMS模板应用调研问卷
截止目前,已经有数十家网站与我们合作,进行了MIP化改造,在搜索结果页也能看到"闪电标"的出现.除了改造方面的问题,MIP项目组被问到最多的就是:我用了wordpress,我用了织 ...
- PHP-自定义模板-学习笔记
1. 开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2. 整体架构图 ...
- 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送
微信支付之微信模板消息推送 今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...
随机推荐
- 利用 Blob 处理 node 层返回的二进制文件流字符串并下载文件
博客地址:https://ainyi.com/65 解释 | 背景 看到标题有点懵逼,哈哈,实际上是后端将文件处理成二进制流,返回到前端,前端处理这个二进制字符串,输出文件或下载 最近公司有个需求是用 ...
- 【深度学习系列】PaddlePaddle垃圾邮件处理实战(二)
PaddlePaddle垃圾邮件处理实战(二) 前文回顾 在上篇文章中我们讲了如何用支持向量机对垃圾邮件进行分类,auc为73.3%,本篇讲继续讲如何用PaddlePaddle实现邮件分类,将深度 ...
- K2开发中,遇到用户无权限OPEN当前的待办
1.用户有的时候在做操作时,提示用户没有权限OPEN当前流程,需要注意判断当前用户是K2标签还是K2SQL标签.如果标签不对,会导致当前问题的发生 后续如果再有碰到,再补充吧
- PHP面向对象和面向过程
编程界不论是PHP.Python都有这么两种编程思想,oop面向对象.pop面向过程,这两种在功能上没有多大区别,但是在代码编写上却有很大区别.今天就记录一下面向对象和面向过程的优点.缺点.定义.实现 ...
- Web前端 web的学习之路
零基础学习web前端的顺序 ( 转载自:https://blog.csdn.net/weixin_41780944/article/details/83751632) 怎么开始学习两条路:自学或者找培 ...
- fab 菜单实现之前传-钟表表盘
个人很喜欢谷歌的material design,很喜欢但是没有动手弄过,今天想动手操作一下Floating Action Button菜单,网上有很多种:圆形.扇形.射线.直线等.我想在一个例子中用到 ...
- Django常见问题
1.什么是中间件? 中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出. 中间件一般做认证或批量请求处理,django中的中间 ...
- FreeNas搭建踩坑指南(二)
0x00 权限配置 FreeNas完成后配置用户组及权限,新建用户和用户组后添加Samba共享(Windows模式),无法准确控制权限,尝试在系统中修改权限提示"Operation not ...
- 五一出门必备的手机APP神器 让你瞬间大开眼界
如今我们手机上有各种各样的软件,但是比较实用的又有哪些呢?所以每次大家都会花上很久的时间去查找满意的软件吧!今天就给大家送上一波福利,因为五一小长假就要到来了,说不定大家会使用到呢! 轻颜相机 轻颜相 ...
- K60用IRA通过j-link下载失败,解决方法
K60在用飞思卡尔原厂的例程时,例程编译时没有问题,但是烧写时不成功,出现以下提示,请问该如何解决这个问题?提示1.Miss or malformed flash loader specificati ...