【模板】2-SAT问题
问题简述
有 \(n\) 个变量,每个变量可赋为 \(1\) 或 \(0\)
必须满足一些限制条件,如“ \(a\) 为1 或 \(b\) 为0 ” “ \(a\) 为0 且 \(b\) 为1” …
判断是否有一种赋值方法满足所有限制条件,并构造答案。
做法
首先拆点,把每个变量 \(i\) 拆成 \(i\) 选1 和 \(i\) 选0 两个点,在这两个点中选出一个
现在我们在 \(2n\) 个点中选出了 \(n\) 个点,相当于选择了一种赋值方案
换句话说,每种赋值方案就是在 每对 \(i\) 选1 和 \(i\) 选0 中选一个点
考虑所有限制条件,有两种类型。
第一种是 “ \(x_i=k_i\) 且 \(x_j=k_j\) ”
我们可以连一些有向边 \((u,v)\),表示如果选了 \(u\) ,就一定要选 \(v\)
那针对这种情况,则要连 \((x_i选k_i, x_j选k_j)\)
但这样还不够!
回忆一下“逆否命题”,我们还需连 \((x_j不选k_j,x_i不选k_i)\) 才可保证限制满足。
第二种是 “ \(x_i=k_i\) 或 \(x_j=k_j\) ”
连边 \((x_i不选k_i, x_j选k_j)\) 和 \((x_j不选k_j,x_i选k_i)\)
这样下来,我们发现连的所有边是对称的!(真命题&逆否命题嘛)
接下来,我们对这个有向图跑强连通分量缩点。
对每个强连通分量,要么都选,要么都不选。
还记得如何选赋值方案吗?
每对\(i\) 选1 和 \(i\) 选0 中只能选1个,那么判断一下,如果这两个点在同一个强连通分量中,则无解。
如果不在,选拓扑排序中拓扑序靠后的那个点,(也就是 \(tarjan\) 中编号较小的那个点),可以保证这样选出的点是一组合理的赋值方案。
代码
洛谷模板题 \(P4782\)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 2000005;
struct node{
int v;
node *nxt;
}pool[N],*h[N];
int cnt;
void addedge(int u,int v){
node *p=&pool[++cnt];
p->v=v;p->nxt=h[u];h[u]=p;
}
int n,m;
int tot;
int dfn[N],low[N],scc,belong[N];
int st[N],top,vis[N];
void tarjan(int u){
int v;
dfn[u]=low[u]=++tot;
vis[u]=1;
st[top++]=u;
for(node *p=h[u];p;p=p->nxt)
if(!dfn[v=p->v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
if(low[u]==dfn[u]){
scc++;
while(1){
belong[st[--top]]=scc;
vis[st[top]]=0;
if(st[top]==u) break;
}
}
}
int main()
{
int a,b,c,d;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d%d%d%d",&a,&b,&c,&d);
addedge(a+(1-b)*n,c+d*n);
addedge(c+(1-d)*n,a+b*n);
}
for(int i=1;i<=2*n;i++)
if(!dfn[i]) tarjan(i);
int flag=0;
for(int i=1;i<=n;i++)
if(belong[i]==belong[i+n]) flag=1;
if(flag) { printf("IMPOSSIBLE\n"); return 0; }
printf("POSSIBLE\n%d",belong[1]>belong[n+1]);
for(int i=2;i<=n;i++) printf(" %d",belong[i]>belong[n+i]);
return 0;
}
【模板】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 微信支付之微信模板消息推送
微信支付之微信模板消息推送 今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...
随机推荐
- error:cannot load file (code:5555h);bootauto.ini
最近发现有的网友在使用Ghost XP盘安装系统的时候,选择一键ghost到C盘出现下面的错误: error:cannot load file (code:5555h);bootauto.ini(或b ...
- ES安装&常见错误
ES常见错误 案例一 [2018-06-20T02:35:47,152][INFO ][o.e.b.BootstrapChecks ] [SUcoFrg] bound or publishing to ...
- 一点资讯 视频抓取 phantomjs
# _*_ coding: utf- _*_ """ 思路: .列表页使用phantomjs模拟点击.每个链接只抓取第一页9-10条内容,按照标题去重 .布置定时任务,每 ...
- 常见的java异常——java.lang.IllegalStateException: Ambiguous handler methods mapped for HTTP path
此异常是由于你的controller中有两个名字与内容相同的方法: 出现此异常时去检查你的controller中是否有重复的名字的方法:
- HashMap面试题解答
一.HashMap的实现原理? 此题可以组成如下连环炮来问 你看过HashMap源码嘛,知道原理嘛?为什么用数组+链表?hash冲突你还知道哪些解决办法?我用LinkedList代替数组结构可以么?既 ...
- 原生JS数组方法实现(一)————push()、unshift()、pop()和shift()
push 向数组末尾添加一个或多个元素,并返回数组新的长度 ```javascript function push(){ for(let i=0;i<arguments.length;i++){ ...
- JDBC 详解笔记
# JDBC ## 1:What? 通过Java代码来操作数据库的. 数据库的种类很多,导致不同的数据库的操作方式是不同. 通过JDBC的标准完成.通过java语言完成对于数据库的CRUD. ## 2 ...
- 1shell基础,变量,运算符
1shell基础语法 是一个命令解释器,在操作系统的最外层,负责直接与用户进行对话. 我们输入的命令,计算机时不识别的,这时就需要一种程序来帮助我们进行翻译,变成计算机能识别的二进制程序,同时把计算机 ...
- AbstractFactoryPattern(抽象工厂模式)-----Java/.Net
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂.该超级工厂又称为其他工厂的工厂.
- 「洛谷P2397」 yyy loves Maths VI (mode) 解题报告
P2397 yyy loves Maths VI (mode) 题目背景 自动上次redbag用加法好好的刁难过了yyy同学以后,yyy十分愤怒.他还击给了redbag一题,但是这题他惊讶的发现自己居 ...