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 ...
随机推荐
- Logger日志配置级别说明及设置方法、说明
日志记录器(Logger)是日志处理的核心组件.log4j具有5种正常级别(Level).日志记录器(Logger)的可用级别Level (不包括自定义级别 Level), 以下内容就是摘自log4j ...
- centos7部署harbor
官网 https://github.com/goharbor/harbor 1.升级系统内核 rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrep ...
- 近年来爆发的CVE漏洞编号
1.Office漏洞 Office漏洞是大部分APT组织最喜爱的漏洞,Office在个人办公电脑使用量大,对针对性目标是最佳的外网入口,效果也是最直接的. CVE编号 漏洞类型 使用组织 CVE-2 ...
- python3.X中pickle类的用法(cPickle模块移除了)
1.python3.x中移除了cPickle模块,可以使用pickle模块代替.最终我们将会有一个透明高效的模块. 2.因为存储的是对象,必须使用二进制形式写进文件 #!/usr/bin/python ...
- 2.1 <script>元素【JavaScript高级程序设计第三版】
向 HTML 页面中插入 JavaScript 的主要方法,就是使用<script>元素.这个元素由 Netscape 创造并在 Netscape Navigator 2 中首先实现.后来 ...
- Hive的数据库和表
本文介绍一下Hive中的数据库(Database/Schema)和表(Table)的基础知识,由于篇幅原因,这里只是一些常用的.基础的. Hive的数据库和表 先看一张草图: Hive结构 从图上可以 ...
- C语言真正的编译过程(4个步骤~~预编译,编译,汇编,连接)
转载自:https://www.cnblogs.com/wuyouxiaocai/p/5701088.html#commentform 说实话,很多人做了很久的C/C++,也用了很多IDE,但是对于可 ...
- 7-1 寻找大富翁 PTA 堆排序
7-1 寻找大富翁 (25 分) 胡润研究院的调查显示,截至2017年底,中国个人资产超过1亿元的高净值人群达15万人.假设给出N个人的个人资产值,请快速找出资产排前M位的大富翁. 输入格式: 输入首 ...
- python基础之继承实现原理、子类调用父类的方法、封装
继承实现原理 python中的类可以同时继承多个父类,继承的顺序有两种:深度优先和广度优先. 一般来讲,经典类在多继承的情况下会按照深度优先的方式查找,新式类会按照广度优先的方式查找 示例解析: 没有 ...
- TouTiao开源项目 分析笔记2
1.Constant常量定义类 1.1.源代码 public class Constant { public static final String USER_AGENT_MOBILE = " ...