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 ...
随机推荐
- 利用deadline_timer实现定时器Timer
// 类似QTimer的定时器 class Timer { typedef void(* handler)(); public: Timer() : m_millseconds() , m_timer ...
- 如何在maven中的项目使用tomcat插件
在pom.xml中引入tomcat7插件,具体示例代码如下: <project> <build> <plugins> <plugin> <grou ...
- POJ:2449-Remmarguts' Date(单源第K短路)
Remmarguts' Date Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 33081 Accepted: 8993 Des ...
- 笔记-python-module-logging.循环日志、多进程日志
笔记-python-module-logging.循环日志.多进程日志 1. logging循环日志 循环日志分为按大小切分和按时间切分,对应实现类如下. 1.1. RotatingFil ...
- spring源码学习中的知识点
一.循环依赖 循环依赖就是循环引用,就是两个或多个bean之间互相持有对方. 1.构造器循环依赖 表示通过构造器注入造成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyInCreat ...
- 05,Python网络爬虫之三种数据解析方式
回顾requests实现数据爬取的流程 指定url 基于requests模块发起请求 获取响应对象中的数据 进行持久化存储 其实,在上述流程中还需要较为重要的一步,就是在持久化存储之前需要进行指定数据 ...
- Android stadio Switch repository Android stadio切换仓库
Android stadio 有时候,有很多module. 这些module 都有自己的仓库.也就是不在一块.那么,Android stadio 默认管理的就是根git. 如图,画对号的就是默认的. ...
- 跨站请求伪造(csrf)中间件整理
一. CSRF中间件 字面意思跨站请求伪造; 即模仿个请求朝服务器发送,django中对跨站伪造的请求有相应的校验 from django.views.decorators.csrf import c ...
- Unicode字符图标
http://unicode-table.com/cn/#control-character
- 剑指Offer - 九度1351 - 数组中只出现一次的数字
剑指Offer - 九度1351 - 数组中只出现一次的数字2013-11-23 01:23 题目描述: 一个整型数组里除了两个数字之外,其他的数字都出现了两次.请写程序找出这两个只出现一次的数字. ...