浅谈2-SAT
引入:
相信大家都了解过差分约束系统。差分约束系统的大体意思就是给出一些有某种关系的变量,问你是否有某种赋值使得这些关系全部成立
其实\(2-SAT\)的题目描述和这个很像(虽然解法不一样)
那么\(2-SAT\)到底是什么呢?
首先,把\(2\)和\(SAT\)拆开。\(SAT\) 是 \(Satisfiability\) 的缩写,意为可满足性。即一串布尔变量,每个变量只能为真或假。要求对这些变量进行赋值,满足布尔方程(摘自\(Anguei\)的题解)
通俗一点来说,就是有\(n\)个bool变量\(x_1\)~\(x_n\)有\(m\)个位运算的表达式(只有两个变量),求是否有一种方法使得\(m\)个表达式都成立
\]
例题
题目背景
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\in {0,1}$)
输出格式
如无解,输出"IMPOSSIBLE"(不带引号); 否则输出"POSSIBLE"(不带引号),下一行\(n\)个整数(\(x_1\)~\(x_n\)\(\in \{0,1\}\)),表示构造出的解。
\]
如何解决这类问题?
首先,我们发现一个变量取值的真和假是相对独立的,也就是说和他自己没有关系,只和其他变量的真假有关系
那我们不妨为每一个变量建两个节点,一个表示真,一个表示假(我这里用1n表示假,n+12n表示真)
有了点,考虑怎么连边。如果一个变量的真假能够推出另一个变量的真假,就对这两个变量对应的真假连边
比如:\(x_1\)为真或\(x_2\)为假,那么\(x_1\)的假就可以推出\(x_2\)的真,\(x_2\)的真就可以推出\(x_1\)的假
那么就把\(x_1\)对应的假节点连向\(x_2\)对应的真节点,把\(x_2\)对应的真节点连向\(x_1\)对应的假节点
如何判断有没有解?
考虑无解的情况,肯定是出现了矛盾,也就是一个点的真推出了它自己的假,或者是这个点的假推出了它自己的真。这种情况有什么特征?
发现如果是这样的话,这个点的真和假一定在相同的强连通分量里面
强联通分量?那不就是tarjan吗?
时间复杂度O(n+m)
那么怎么找出满足题意的解?
当\(x\)所在的强连通分量的拓扑序在\(\neg x\)之后时,直接取\(x\)为真就行了。tarjan算法在执行的过程中已经为每一个强连通分量标好了拓扑序(不过是和正常的拓扑序相反)
#include<bits/stdc++.h>
using namespace std;
const int N=2000050;
int head[N],ecnt;//1~n存0,n+1~2n存1
struct edge
{
int to,nxt;
}edg[N<<1];
inline void add(int u,int v)
{
edg[++ecnt].to=v;
edg[ecnt].nxt=head[u];
head[u]=ecnt;
}
int n,m;
inline void read()
{
for(int i=1;i<=m;i++)
{
int x,a,y,b;
scanf("%d%d%d%d",&x,&a,&y,&b);//建边
if(a==1&&b==1) add(x,y+n),add(y,x+n);
if(a==0&&b==1) add(x+n,y+n),add(y,x);
if(a==1&&b==0) add(x,y),add(y+n,x+n);
if(a==0&&b==0) add(x+n,y),add(y+n,x);
}
}
//tarjan
int dfn[N],low[N],in[N],s[N],scc[N],top,ind,cnt;
void tarjan(int x)
{
low[x]=dfn[x]=++ind;
s[top++]=x;
in[x]=1;
for(int i=head[x];i;i=edg[i].nxt)
{
int v=edg[i].to;
if(!dfn[v])
{
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(in[v]) low[x]=min(low[x],dfn[v]);
}
if(dfn[x]==low[x])
{
cnt++;
while(s[top]!=x)
{
top--;
in[s[top]]=0;
scc[s[top]]=cnt;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
read();
for(int i=1;i<=2*n;i++)
{
if(!dfn[i]) tarjan(i);
}
for(int i=1;i<=n;i++) if(scc[i]==scc[i+n]) return cout<<"IMPOSSIBLE",0;
puts("POSSIBLE");
for(int i=1;i<=n;i++) printf("%d ",scc[i]>scc[i+n]);
}
浅谈2-SAT的更多相关文章
- 【WebApi系列】浅谈HTTP
[01]浅谈HTTP在WebApi开发中的运用 [02]聊聊WebApi体系结构 [03]详解WebApi如何传递参数 [04]详解WebApi测试和PostMan [05]浅谈WebApi Core ...
- 【WebApi系列】浅谈HTTP在WebApi开发中的运用
WebApi系列文章 [01]浅谈HTTP在WebApi开发中的运用 [02]聊聊WebApi体系结构 [03]详解WebApi参数的传递 [04]详解WebApi测试和PostMan [05]浅谈W ...
- 浅谈 Fragment 生命周期
版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/Fragment 文中如有纰漏,欢迎大家留言指出. Fragment 是在 Android 3.0 中 ...
- 浅谈 LayoutInflater
浅谈 LayoutInflater 版权声明:本文为博主原创文章,未经博主允许不得转载. 微博:厉圣杰 源码:AndroidDemo/View 文中如有纰漏,欢迎大家留言指出. 在 Android 的 ...
- 浅谈Java的throw与throws
转载:http://blog.csdn.net/luoweifu/article/details/10721543 我进行了一些加工,不是本人原创但比原博主要更完善~ 浅谈Java异常 以前虽然知道一 ...
- 浅谈SQL注入风险 - 一个Login拿下Server
前两天,带着学生们学习了简单的ASP.NET MVC,通过ADO.NET方式连接数据库,实现增删改查. 可能有一部分学生提前预习过,在我写登录SQL的时候,他们鄙视我说:“老师你这SQL有注入,随便都 ...
- 浅谈WebService的版本兼容性设计
在现在大型的项目或者软件开发中,一般都会有很多种终端, PC端比如Winform.WebForm,移动端,比如各种Native客户端(iOS, Android, WP),Html5等,我们要满足以上所 ...
- 浅谈angular2+ionic2
浅谈angular2+ionic2 前言: 不要用angular的语法去写angular2,有人说二者就像Java和JavaScript的区别. 1. 项目所用:angular2+ionic2 ...
- iOS开发之浅谈MVVM的架构设计与团队协作
今天写这篇博客是想达到抛砖引玉的作用,想与大家交流一下思想,相互学习,博文中有不足之处还望大家批评指正.本篇博客的内容沿袭以往博客的风格,也是以干货为主,偶尔扯扯咸蛋(哈哈~不好好工作又开始发表博客啦 ...
- Linux特殊符号浅谈
Linux特殊字符浅谈 我们经常跟键盘上面那些特殊符号比如(?.!.~...)打交道,其实在Linux有其独特的含义,大致可以分为三类:Linux特殊符号.通配符.正则表达式. Linux特殊符号又可 ...
随机推荐
- eclipses配置tomcat
1,项目右键属性,设置为1.8,与jdk相对应 2,自动发布,tomcat 3,使用自己的tomcat 4,
- 忘记oracle的sys用户密码如何修改以及Oracle 11g 默认用户名和密码
忘记除SYS.SYSTEM用户之外的用户的登录密码 CONN SYS/PASS_WORD AS SYSDBA; --用SYS (或SYSTEM)用户登录 ALTER USER user_name ID ...
- php连接阿里云mysql
1.开启Mysql远程访问端口 现在服务器控制台,安全组那边开启3306端口 2.修改Mysql配置文件 vim /etc/mysql/mysql.conf.d/mysqld.cnf,找到bind-a ...
- mysql统计表中条目个数的方法举例
说明:以下标红且加大括号的均需要替换为实际待查询的表名或数据库名. [1].统计某张或某几张表的数据量: select count(*) from {TABLE_NAME}; #or select c ...
- TIOBE 7月排行:Python 过分炒作,Perl 成受害者?
与上个月相比,Python 的指数又增加了不少,由 8.530% 上升到 9.260%. 我们还留意到,TIOBE 对这期榜单的标题描述是“Perl is one of the victims of ...
- Java入门指南-04 顺序、分支、循环
顺序结构 从上至下,依次执行 if 语句在 Java 里,用 if 语句来实现“当满足 XXX 条件时,执行 YYY”这样的逻辑判断.例如,在使用共享单车时需要检查人的年纪.如果在 12 岁以下,则禁 ...
- 模拟赛小结:2017 China Collegiate Programming Contest Final (CCPC-Final 2017)
比赛链接:传送门 前期大顺风,2:30金区中游.后期开题乏力,掉到银尾.4:59绝杀I,但罚时太高卡在银首. Problem A - Dogs and Cages 00:09:45 (+) Solve ...
- D-query SPOJ - DQUERY (莫队算法裸题)
Given a sequence of n numbers a1, a2, ..., an and a number of d-queries. A d-query is a pair (i, j) ...
- filter和filter_by 的区别
- k8s命令集锦
集群环境相关命令$kubectl vertion --short=true #显示当前使用的客户端及服务端程序版本信息$kubectl cluster-info #获取集群信息$kubectl api ...