【模板】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. 你不知道的JavaScript(五)内置对象模版

    尽管JavaScript中有对象的概念,但一般我们并不说JavaScript是面向对象的编程语言,因为它不具备面向对象的一些最基本特征. 在c++/Java等这些面向对象的编程语言中,我们要定义一个对 ...

  2. 51nod 1096 距离之和最小 思维题,求中位数

    题目: 在一条直线上,与两个点距离之和最小的点,是怎样的点? 很容易想到,所求的点在这两个已知点的中间,因为两点之间距离最短. 在一条直线上,与三个点距离之和最小的点,是怎样的点? 由两个点的规律,我 ...

  3. hdu 2037 - 典型贪心*

    题目链接 给一堆电视节目的起止时间,问最多能完整收看几个节目 --------------------------------------------------------------------- ...

  4. ACM-ICPC 2018 徐州赛区网络预赛 H. Ryuji doesn't want to study(树状数组)

    Output For each question, output one line with one integer represent the answer. 样例输入 5 3 1 2 3 4 5 ...

  5. (2016北京集训十四)【xsy1556】股神小D - LCT

    题解: 题解居然是LCT……受教了 把所有区间按照端点排序,动态维护目前有重叠的区间,用LCT维护即可. 代码: #include<algorithm> #include<iostr ...

  6. CF504E Misha and LCP on Tree(树链剖分+后缀树组)

    1A真舒服. 喜闻乐见的树链剖分+SA. 一个初步的想法就是用树链剖分,把两个字符串求出然后hash+二分求lcp...不存在的. 因为考虑到这个字符串是有序的,我们需要把每一条重链对应的字符串和这个 ...

  7. luogu P1592 互质(欧拉函数)

    题意 (n<=106,k<=108) 题解 一开始以为是搜索. 但想想不对,翻了一眼题解发现是欧拉函数. 因为 gcd(a,b)=gcd(a,a+b) 所以和n互质的数应该是类似a1,a2 ...

  8. POJ——T 1469 COURSES

    http://poj.org/problem?id=1469 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 24197   ...

  9. POJ——T2446 Chessboard

    http://poj.org/problem?id=2446 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18560   ...

  10. Python 入门学习 -----变量及基础类型(元组,列表,字典,集合)

    Python的变量和数据类型 1 .python的变量是不须要事先定义数据类型的.能够动态的改变 2. Python其中一切皆对象,变量也是一个对象,有自己的属性和方法 我们能够通过 来查看变量的类型 ...