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 问题的目标是给每个变量赋值使得所有条件得到满足。
二、逻辑关系
这里不用太过专业的符号来说明逻辑关系,仅仅是感性说明(没错就是我菜)
设条件为大写字母A,B,非A,非B只条件的另一种取值
A或者B 等价于 非A则B 和 非B则A
注意到后面两个要求似乎有蜜汁对称性,而且它们都是有向的
根据后一句话,我们借助并查集扩展域的思想,把一个点的两个取值拆开,进行建图
三、建图
这里就画图举例说明吧
给出这样三个条件\((1,1)\)或\((2,1)\),\((2,1)\)或\((3,1)\),\((2,0)\)或(3,1)$
\((x,y)\)表示\(x\)需要取值\(y\)
我们把点\(x\)取值\(0\)的点编号\(x\),取值\(1\)的点编号\(x+n\)
我们可以建出如下的图
有向边\((u,v)\)表示如果\(u\)选,\(v\)一定选
很显然这是有解的,我们可以去\(1,2,3\)等点集
怎么样才会无解呢?
如果一个点的出边的点构成的集合中又出现了它自己?这样可以不选它而选另一个值啊
如果这个集合出现了另一个值呢?
好吧,这里的无解其实就是综合一下,选它的同时要选它的另一个值,选它的另一个值同时要选它
等价于两者在有向图中处于同一个环中
这样我们就可以通过tarjan求环来判断有解性了
四、构造合法方案
如果一个点没有伸出去的边,就代表它不约束别人,我们可以随便选择选或不选它
设\(cho[]\),若\(cho[x]==0\)则代表我们选择了它,否则我们没有选择它
优先选择出度为0的点
我们可以在缩点后的图中反向建图,然后做拓扑排序
注意我们选择一个点后,要把它对应的点置不选
事实上,我们也可以没必要做这么麻烦
dfs遍历的DAG图的序列反过来其实就是反向建边的拓扑序
在tarjan中先做的点的编号就是反向建边拓扑序
那么我们直接比编号大小进行赋值就可以啦
五、参考代码
#include <cstdio>
int min(int x,int y){return x<y?x:y;}
const int N=2e6+10;
int head[N],to[N<<1],Next[N<<1],cnt,n,m;
void add(int u,int v)
{
to[++cnt]=v;Next[cnt]=head[u];head[u]=cnt;
}
void init()
{
scanf("%d%d",&n,&m);
for(int i,a,j,b,k=1;k<=m;k++)
{
scanf("%d%d%d%d",&i,&a,&j,&b);
add(i+(1-a)*n,j+b*n),add(j+(1-b)*n,i+a*n);
}
}
int dfn[N],low[N],in[N],s[N],ha[N],tot,dfs_clock,n_;
void tarjan(int now)
{
dfn[now]=low[now]=++dfs_clock;
s[++tot]=now;
in[now]=1;
for(int i=head[now];i;i=Next[i])
{
int v=to[i];
if(!dfn[v])
{
tarjan(v);
low[now]=min(low[now],low[v]);
}
else if(in[v])
low[now]=min(low[now],dfn[v]);
}
if(low[now]==dfn[now])
{
int k;++n_;
do
{
k=s[tot--];
ha[k]=n_;
in[k]=0;
}while(k!=now);
}
}
void work()
{
for(int i=1;i<=n<<1;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
if(ha[i]==ha[i+n])
{
printf("IMPOSSIBLE\n");
return;
}
printf("POSSIBLE\n");
for(int i=1;i<=n;i++)
printf("%d ",ha[i]>ha[i+n]);
}
int main()
{
init();
work();
return 0;
}
2018.9.1
2-sat 学习笔记的更多相关文章
- <老友记>学习笔记
这是六个人的故事,从不服输而又有强烈控制欲的monica,未经世事的千金大小姐rachel,正直又专情的ross,幽默风趣的chandle,古怪迷人的phoebe,花心天真的joey——六个好友之间的 ...
- OGG学习笔记02-单向复制配置实例
OGG学习笔记02-单向复制配置实例 实验环境: 源端:192.168.1.30,Oracle 10.2.0.5 单实例 目标端:192.168.1.31,Oracle 10.2.0.5 单实例 1. ...
- python数据分析入门学习笔记
学习利用python进行数据分析的笔记&下星期二内部交流会要讲的内容,一并分享给大家.博主粗心大意,有什么不对的地方欢迎指正~还有许多尚待完善的地方,待我一边学习一边完善~ 前言:各种和数据分 ...
- 【MarkMark学习笔记学习笔记】javascript/js 学习笔记
1.0, 概述.JavaScript是ECMAScript的实现之一 2.0,在HTML中使用JavaScript. 2.1 3.0,基本概念 3.1,ECMAScript中的一切(变量,函数名,操作 ...
- Linux 学习笔记之超详细基础linux命令 Part 13
Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 12---------------- ...
- Linux 学习笔记之超详细基础linux命令 Part 8
Linux学习笔记之超详细基础linux命令 by:授客 QQ:1033553122 ---------------------------------接Part 7----------------- ...
- Deep learning with Python 学习笔记(5)
本节讲深度学习用于文本和序列 用于处理序列的两种基本的深度学习算法分别是循环神经网络(recurrent neural network)和一维卷积神经网络(1D convnet) 与其他所有神经网络一 ...
- 【Redis】命令学习笔记——字符串(String)(23个超全字典版)
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). 本篇基于redis 4.0.11版本,学习字符串( ...
- programming-languages学习笔记--第3部分
programming-languages学习笔记–第3部分 */--> pre.src {background-color: #292b2e; color: #b2b2b2;} pre.src ...
- 学习笔记 - 2sat
学习笔记 - 2sat 决定重新启用Markdown--只是因为它支持MathJax数学公式 noip考完,既轻松又无奈,回来慢慢填坑 这篇博客也是拖了好久,通过kuangbin的博客才弄懂2-sat ...
随机推荐
- Linq to SQL八大子句
查询数据库中的数据 from- in子句 指定查询操作的数据源和范围变量 select子句 指定查询结果的类型和表现形式 where子句 筛选元素的逻辑条件,一般由逻辑运算符组成 group- by子 ...
- TCL之表达式
- JDK学习---深入理解java中的String
本文参考资料: 1.<深入理解jvm虚拟机> 2.<大话数据结构>.<大话设计模式> 3.http://www.cnblogs.com/ITtangtang/p/3 ...
- iar注释快捷键
选中多行后注释快捷键:Ctrl+K 取消多行注释快捷键:Ctrl+Shift+K
- [USACO5.1]夜空繁星Starry Night
题目背景 高高的星空,簇簇闪耀的群星形态万千.一个星座(cluster)是一群连通的星组成的非空连通星系,这里的连通是指水平,垂直或者对角相邻的两个星星.一个星座不能是另一个更大星座的一部分, 星座可 ...
- C++基础 const
1. C中的const C中const变量只是只读变量,有自己存储空间.可能被存放在 栈.堆.数据段,所以可以修改. 2. C++中const 可能分配空间,也可能不分配空间. 当 const 为全局 ...
- 02,Python网络爬虫第二弹《http和https协议》
一.HTTP协议 1.官方概念: HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文 ...
- android 布局preview 技巧
最近开始看老外写的文章,博客,嗯,不能说比国人写的好,但是感觉看着很爽.真的,一手资料就是爽. 嗯,自己做得不错,第一次看外文博客,我知道自己怎么看的,一句话一句话看下来的,越看越有感觉. 下面这个 ...
- JavaSE总结--异常
throwable Error: Exception: 编译型异常: 运行时异常:
- javascript 数组的常用方法总结
前言 主要讨论一下数组的方法, 1.splice和slice的区别 2.pop和push 3.shift和unshift 4.join 5.forEach(es ...