【模板】2-SAT 问题(2-SAT)
【模板】2-SAT 问题
题目背景
2-SAT 问题 模板
题目描述
有n个布尔变量 \(x_1\) ~ \(x_n\) ,另有m个需要满足的条件,每个条件的形式都是“ \(x_i\) 为true/false或 \(x_j\) 为true/false”。比如“ \(x_1\) 为真或 \(x_3\) 为假”、“ \(x_7\) 为假或 \(x_2\) 为假”。2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。
输入输出格式
输入格式:
第一行两个整数n和m,意义如体面所述。
接下来m行每行4个整数 i a j b,表示“ \(x_i\) 为a或 \(x_j\) 为b”(a,b∈{0,1})
输出格式:
如无解,输出“IMPOSSIBLE”(不带引号); 否则输出"POSSIBLE"(不带引号),下 一行n个整数 \(x_1\) ~ \(x_n\) (\(x_i\)∈{0,1}),表示构造出的解。
输入输出样例
输入样例#1: 复制
3 1
1 1 3 0
输出样例#1: 复制
POSSIBLE
0 0 0
题解
谈谈理解?
只会\(n+m\)时间复杂度的算法。
对于一个2-sat问题。有如下三种情况
1.如果A=1 那么 B=1
转化为图论思想,如果我要选A则必须选B
不选A则一定不选B
对(A,B),(B1,A1)建边。
2.要么A=1,要么B=1
那就是
选A就不选B(A,B^1),
选B就不选A(B,A^1)
3.A一定要选
直接连边(A^1,A)
首先可以知道, \(x_{i,0}\) 和 \(x_{i,1}\) 必须选择且仅选择一个。那么,因为 \(x_i=a\) 一定满足,则 \(x_i!=a\) 的点不可以取。那么,直接建边 \((x_{i,a\oplus1}x_{i,a})\) 可以控制 \(x_{i,a\oplus1}\), 这个点一定不可选择,否则无解。
然后用tarjan求一遍强联通分量。可以发现每一个强联通分量里面的情况是要么选就一起选,不选就一起不选的。当一个条件与它的反条件同时被选取,即在一个强联通分量时,是不成立的。要么就是成立的。
那么输出呢?怎么保证输出的方案是正确?
根据2-sat的对称原则。如果连的是双向边,那么整个图就是对称的。那么为什么比较拓扑序就一定正确呢?
因为由对称原则强联通分量一定也是相同的。而根据强联通分量被标记的时间顺序,拓扑序一定能保证每个问题有正确解。
(好吧,还是有点绕)
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int N=3000001;
int head[N],dfn[N],low[N];
int id,tot,num,cnt;
int n,m,top;
int vis[N],line[N],bl[N];
struct node{
int to,nex;
}e[N<<1];
int read(){
int x=0,w=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
return x*w;
}
void add(int from,int to){
num++;
e[num].to=to;
e[num].nex=head[from];
head[from]=num;
}
void tarjan(int x){
dfn[x]=low[x]=++id;
line[++top]=x;vis[x]=1;
for(int i=head[x];i;i=e[i].nex){
int v=e[i].to;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(vis[v])
low[x]=min(low[x],dfn[v]);
}
if(low[x]==dfn[x]){
cnt++;
while(line[top+1]!=x){
int u=line[top];
bl[u]=cnt;
vis[u]=0;
top--;
}
}
}
bool T_sat(){
for(int i=1;i<=n+n;i++)
if(!dfn[i])tarjan(i);
for(int i=1;i<=n;i++)
if(bl[i]==bl[n+i])return false;
return true;
}
int main(){
n=read();m=read();
for(int i=1;i<=m;i++){
int x=read(),a=read(),y=read(),b=read();
add(x+n*(a^1),y+n*b);add(y+n*(b^1),x+n*a);
}
if(T_sat()){
printf("POSSIBLE\n");
for(int i=1;i<=n;i++)
printf("%d ",bl[i]>bl[i+n]);
}
else printf("IMPOSSIBLE\n");
return 0;
}
【模板】2-SAT 问题(2-SAT)的更多相关文章
- 2 - sat 模板(自用)
2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一 POJ 3207 Ikki's Story IV ...
- 《Linux命令行与shell脚本编程大全》第二十章 正则表达式
20.1 什么是正则表达式 20.1.1 定义 正则表达式是你所定义的模式模板.linux工具可以用它来过滤文本. 正则表达式利用通配符来描述数据流中第一个或多个字符. 正则表达式模式含有文本或特殊字 ...
- DirectX11 With Windows SDK--11 混合状态与光栅化状态
前言 虽然这一部分的内容主要偏向于混合(Blending),但这里还需提及一下,关于渲染管线可以绑定的状态主要有如下四种: 光栅化状态(光栅化阶段) 采样器状态(像素着色阶段) 混合状态(输出合并阶段 ...
- MySQL-MHA集群部署(binlog复制)
MHA的理论知识网上有很多教程,这里不会说明:仅推荐博客链接! MHA的理论说明:http://www.ywnds.com/?p=8094 MHA的安装包需要在google上面下载,或者就是csdn上 ...
- 浅谈2-SAT
引入: 相信大家都了解过差分约束系统.差分约束系统的大体意思就是给出一些有某种关系的变量,问你是否有某种赋值使得这些关系全部成立 其实\(2-SAT\)的题目描述和这个很像(虽然解法不一样) 那么\( ...
- DirectX11 With Windows SDK--11 混合状态
原文:DirectX11 With Windows SDK--11 混合状态 前言 这一章会着重讲述混合状态,在下一章则会讲述深度/模板状态 DirectX11 With Windows SDK完整目 ...
- Enter password for default keyring to unlock
file /home/ok/.gnome2/keyrings/login.keyring /home/ok/.gnome2/keyrings/login.keyring: GNOME keyring, ...
- 原来还有这样的记词方法_Java版记不规则动词_博主推荐
昨天在看一本英语书的不规则动词的时候,突然产生的灵感:就是想把这样记单词简单方式,用程序代码实现,然后,使用户可以与之进行交互 这样,在用户背不规则动词的时候就会轻松把它给记住.基于这一点,于是我就思 ...
- FTP常用故障代码注解
FTP错误列表 出处:http://bbs.enet.com.cn/UserControl?act=13&threadID 作者: |秒杀』| 详细的FTP错误列表 Restart marke ...
- python中数据的变量和字符串的常用使用方法
1.查看变量类型: a=2 print(a,type(a)) print的用法:在print后面跟多个输出,可以用逗号分隔. 回收变量名,如把a存储不同的数据,你不需要删除原有变量就可以直接赋值 2. ...
随机推荐
- XShell与虚拟机连接的IP问题
这几天在Xshell连接虚拟机这个问题上头疼了好长时间,原因是我在虚拟机内的eth0网卡没有分配IP地址,从而导致无法连接XShell,今天解决了这个问题,做一下记录. 首先我使用的是微软的Hyper ...
- ActiveMQ学习笔记(5)----Broker的启动方式
Broker:相当于一个ActiveMQ服务器实例,在实际的开发中我们可以启动多个Broker. 命令行启动参数示例如下: 1. activemq start 使用默认的activemq.xml来启动 ...
- 模拟post提交
模拟post提交 function post(URL, PARAMS) { var temp = document.createElement("form"); temp.acti ...
- BZOJ 2119 股市的预测(后缀数组)
首先要差分+离散化. 然后就是求形如ABA的串有多少,其中B的长度确定为k. 我们用到了设置关键点的思想.我们枚举A的长度L.然后在\(1,1+L,1+L*2,1+L*3...\)设置关键点.然后我们 ...
- 第五周-磁盘分区GPT、shell脚本练习、lvm详解
1. 描述GPT是什么,应该怎么使用 Linux中磁盘分区分为MBR和GPT. MBR全称为Master Boot Record,为主引导记录,是传统的分区机制,应用于绝大多数使用的BIOS的PC设备 ...
- pip 出错
pip 升级到10以上出错 ImportError: cannot import name 'main' 解决方法一: 降低pip的版本号 python -m pip install pip==9.0 ...
- python scrapy爬取HBS 汉堡南美航运公司柜号信息
下面分享个scrapy的例子 利用scrapy爬取HBS 船公司柜号信息 1.前期准备 查询提单号下的柜号有哪些,主要是在下面的网站上,输入提单号,然后点击查询 https://www.hamburg ...
- [luogu] P4514 上帝造题的七分钟 (树状数组,二维差分)
P4514 上帝造题的七分钟 题目背景 裸体就意味着身体. 题目描述 "第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a ...
- Java基础学习总结(5)——多态
一.面向对象最核心的机制--动态绑定,也叫多态 1.1.通过下面的例子理解动态绑定,即多态 package javastudy.summary; class Animal { /** * 声明一个私有 ...
- ASP.NET-webconfig中注意事项
正确的写法是这样的 正常解析含有html的代码需要@Html.Raw(ViewBag.ss); 直接使用@ViewBag.ss来显示只能显示源代码,像这样 来自为知笔记(Wiz)