【模板】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)的更多相关文章

  1. 2 - sat 模板(自用)

    2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一  POJ 3207 Ikki's Story IV ...

  2. 《Linux命令行与shell脚本编程大全》第二十章 正则表达式

    20.1 什么是正则表达式 20.1.1 定义 正则表达式是你所定义的模式模板.linux工具可以用它来过滤文本. 正则表达式利用通配符来描述数据流中第一个或多个字符. 正则表达式模式含有文本或特殊字 ...

  3. DirectX11 With Windows SDK--11 混合状态与光栅化状态

    前言 虽然这一部分的内容主要偏向于混合(Blending),但这里还需提及一下,关于渲染管线可以绑定的状态主要有如下四种: 光栅化状态(光栅化阶段) 采样器状态(像素着色阶段) 混合状态(输出合并阶段 ...

  4. MySQL-MHA集群部署(binlog复制)

    MHA的理论知识网上有很多教程,这里不会说明:仅推荐博客链接! MHA的理论说明:http://www.ywnds.com/?p=8094 MHA的安装包需要在google上面下载,或者就是csdn上 ...

  5. 浅谈2-SAT

    引入: 相信大家都了解过差分约束系统.差分约束系统的大体意思就是给出一些有某种关系的变量,问你是否有某种赋值使得这些关系全部成立 其实\(2-SAT\)的题目描述和这个很像(虽然解法不一样) 那么\( ...

  6. DirectX11 With Windows SDK--11 混合状态

    原文:DirectX11 With Windows SDK--11 混合状态 前言 这一章会着重讲述混合状态,在下一章则会讲述深度/模板状态 DirectX11 With Windows SDK完整目 ...

  7. Enter password for default keyring to unlock

    file /home/ok/.gnome2/keyrings/login.keyring /home/ok/.gnome2/keyrings/login.keyring: GNOME keyring, ...

  8. 原来还有这样的记词方法_Java版记不规则动词_博主推荐

    昨天在看一本英语书的不规则动词的时候,突然产生的灵感:就是想把这样记单词简单方式,用程序代码实现,然后,使用户可以与之进行交互 这样,在用户背不规则动词的时候就会轻松把它给记住.基于这一点,于是我就思 ...

  9. FTP常用故障代码注解

    FTP错误列表 出处:http://bbs.enet.com.cn/UserControl?act=13&threadID 作者: |秒杀』| 详细的FTP错误列表 Restart marke ...

  10. python中数据的变量和字符串的常用使用方法

    1.查看变量类型: a=2 print(a,type(a)) print的用法:在print后面跟多个输出,可以用逗号分隔. 回收变量名,如把a存储不同的数据,你不需要删除原有变量就可以直接赋值 2. ...

随机推荐

  1. 【英雄会】微软题目:几个bing

    今天是元旦,开篇先祝福大家在新的一年心想事成,工作顺利,开心生活每一天 . 看到[英雄会]上出现了微软出的题目:几个bing,题目内容如下: 本届大赛由微软必应词典冠名,必应词典(Bing Dicti ...

  2. C# 比较两个数据的不同

    string[] arrRate = new string[] { "op1010", "op1020", "op1030", " ...

  3. sftp权限

    用户: t1 t2 根目录: /home/data/ /home/data/t1/ drwxr-xr-x. 2 t1 t1 4096 Mar 24 17:26 t1 /home/data/t2/ dr ...

  4. js函数参数理解

    eg: function setName(obj){ obj.name = "Nicholas"; obj = new Object(); obj.name = "Gre ...

  5. BZOJ 3881 [Coci2015]Divljak(AC自动机+树状数组)

    建立AC自动机然后,加入一个串之后考虑这个串的贡献.我们把这个串扔到AC自动机里面跑.最后对经过每一个点到的这个点在fail树的根的路径上的点有1的贡献.求链的并,我们把这些点按DFS序排序,然后把每 ...

  6. ansible搭建mysql主主模式

    ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fabric)等优点,实现了批量系统配置.批量程序部署.批量运行命 ...

  7. Ubuntu 16.04 Chrome浏览器安装flash player插件

    1:官网下载插件  flash palyer lash_player_npapi_linux_debug.x86_64.tar.gz 2:解压 提取 libpepflashplayer.so 3:手动 ...

  8. MAVEN flex

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  9. dva基本用法

    1. npm install -g dva-cli 全局安装dva.2. dva new myApp --demo 创建dva项目.3. cd myApp npm start 启动项目.4. 定义 m ...

  10. Qt之图形(组合)

    简述 使用QPainter绘制图形或者图像时,在重叠区域使用组合模式(Composition_mode).在绘图设备上通过组合模式使用QImage时,必须使用Format_ARGB32_Premult ...