前置知识

强连通分量

k-SAT问题

k-SAT问题中的SAT意思就是(stability),也就是适应性问题。本意是给出n个变量,每一个变量有k个状态,并且也给出一些约束条件,要求你求出是否存在每一个变量的取值方案(状态分配方案)。

很可惜,k-SAT(k>2)已经被证明是NP完全的问题了,也就是说我们无法用一些多项式时间复杂度的算法来解决这个问题,但是我们可以发现。当k<=2的时候,我们可以用一些多项式时间复杂度的算法来解决这个问题。

2-SAT问题

先来一道模板题:

Luogu P4782

下面是对2-sat问题的一个例子

假如你是一个厨师,现在要给两个人做菜,每个人的口味都不同,而你至少要满足每个人的一个口味。这些人会提一些要求,比方说:

A:

  • 我不喜欢吃辣椒(-a)
  • 我喜欢吃肥肉有(b)

B:

  • 我不喜欢吃辣椒(-a)
  • 我不喜欢吃肥肉(-b)

那么我们可以用这种形式来简化表示约束条件:

A: -a or B: -a

A: b or B -b

对于每一个\(x_i\) or \(x_j\)的约束条件,我们可以将其变化成:

若\(x_i\)为假则\(x_j\)为真

若\(x_i\)为真则\(x_j\)为假

就比如说 A:-a or B:-b 可以变成

若 A:-a为假,则B: -b为真

若 B:-b为假,则A:-a为真

对上面的例子进行缩写,可以得到:

若A为a,则B为-b

若B为b,则A为-a

(因为-a为假的话证明肯定就是a了,反之亦然,同时也适用于b的情况)

于是,对于每一种约束条件的格式,我们都可以像上面这样分析,然后发现一些传递的关系:

我们把每一个变量抽象成图上的两个点,两个点分别代表了原来一个变量的两个不同的状态。也就是说变成a 和 -a (就是a真和a假)。

我们可以针对每一种约束条件把相对应的关系传递用有向边连接起来,表示从A的某一个状态可以推测出B的值(或者是b的某一个状态可以推得a的状态),也就是说这会形成一些链,在链上的每一个变量的值都是确定了的。但是根据数据的不同,实际上会出现强连通分量。并且如果一个强连通分量中包括某一个和原来a取值相反的-a的取值,则代表其矛盾,也就是说无解

我们这里使用tarjan求SCC(强连通分量)的算法来检测环的出现与否。

那么当问题有解的时候,我们该如何显示每一个变量的值呢?难道我们还需要对原图进行拓扑+染色吗?实际上我们并不需要这么做。因为我们在tarjan的过程中实际上就已经相当于求了一遍拓扑排序了。可以这么想,因为最后我们赋值scc的时候是从栈内弹出赋值的,也就是说越靠近叶子的节点越先被赋值,总的来看这不就是拓扑序的逆序吗?我们可以直接对比a和-a的拓扑序,哪个小就表明哪个是在越靠经根节点处被选中的,那么我们就优先选择哪个比较小的节点。

当然,因为这里我们存储的是拓扑的逆序,所以我们会优先选择哪个比较大的节点

一些代码处理的细节

虽然我们分析问题的时候经常会用a 或-a来表示某个变量的两种状态,但是数组的下标不能是负数。这里我们可以简单地表示-a为a+n,n就是点数。

如果完全按照每一种xi和xj的取值来写代码的话,就会是这个样子的:

for (int i=1;i<=m;i++) {
int a,va,b,vb;
scanf("%d %d %d %d",&a,&va,&b,&vb);
if (va && vb) { // a, b 都真,-a -> b, -b -> a
gpe[a+n].push_back(b);
gpe[b+n].push_back(a);
} else if (!va && vb) { // a 假 b 真,a -> b, -b -> -a
gpe[a].push_back(b);
gpe[b+n].push_back(a+n);
} else if (va && !vb) { // a 真 b 假,-a -> -b, b -> a
gpe[a+n].push_back(b+n);
gpe[b].push_back(a);
} else if (!va && !vb) { // a, b 都假,a -> -b, b -> -a
gpe[a].push_back(b+n);
gpe[b].push_back(a+n);
}
}

当然这么写是正确的,但是代码不可避免地有点冗长,这里我们可以使用位运算的写法可以缩短代码长度:

for(int i=1;i<=m;i++){
int a,va,b,vb;
scanf("%d %d %d %d",&a,&va,&b,&vb);
gpe[a+n*(va&1)].push_back(b+n*(vb^1));
gpe[b+n*(vb&1)].push_back(a+n*(va^1));
}

模板题AC代码:

//luogu p4782
#include <bits/stdc++.h>
using namespace std;
const int maxn=2000050;
struct edge{
int to;
edge(int to_){
to=to_;
}
};
vector<edge> gpe[maxn];
int dfn[maxn],low[maxn],ins[maxn],scc[maxn],size[maxn],cnt=0,sccn=0;
stack<int> s;
void tarjan(int u){
dfn[u]=low[u]=++cnt;
s.push(u);
ins[u]=1;
for(int i=0;i<gpe[u].size();i++){
int v=gpe[u][i].to;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}else if(ins[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(low[u]==dfn[u]){
ins[u]=0;
scc[u]=++sccn;
size[sccn]=1;
while(s.top()!=u){
scc[s.top()]=sccn;
ins[s.top()]=0;
size[sccn]+=1;//这里的size实际上是不需要的
s.pop();
}
s.pop();
}
return;
}
int n,m,oud[maxn];
int main(void){
scanf("%d %d",&n,&m);
memset(low,0x3f,sizeof(low));
memset(ins,0,sizeof(ins));
for(int i=1;i<=m;i++){
int a,va,b,vb;
scanf("%d %d %d %d",&a,&va,&b,&vb);
gpe[a+n*(va&1)].push_back(b+n*(vb^1));
gpe[b+n*(vb&1)].push_back(a+n*(va^1));
}
for(int i=1;i<=n*2;i++){
if(!dfn[i]){
tarjan(i);
}
}
for(int i=1;i<=n;i++){
if(scc[i]==scc[i+n]){
printf("IMPOSSIBLE");
return 0;
}
}
printf("POSSIBLE\n");
for(int i=1;i<=n;i++){
printf("%d ",scc[i]<scc[i+n]);
}
return 0;
}

个人的xbb

其实这个问题感觉和差分约束有一点神似,因为都是根据关系来转换到图上解决的问题

看到自己以前写的代码感觉还是太蠢了qaq,但是反正也懒得改,就直接贴上去罢了

2-SAT问题简述的更多相关文章

  1. 简述WebService的使用(二)

    上集回顾 上一篇我简单的介绍了一下整个WebService建立和后端访问的过程,如果感兴趣可以看一看:简述WebService的使用(一) //如有不懂请留言,觉得有用请点赞 内容提要 这一篇主要介绍 ...

  2. 简述 OAuth 2.0 的运作流程

    本文将以用户使用 github 登录网站留言为例,简述 OAuth 2.0 的运作流程. 假如我有一个网站,你是我网站上的访客,看了文章想留言表示「朕已阅」,留言时发现有这个网站的帐号才能够留言,此时 ...

  3. JavaScript单线程和浏览器事件循环简述

    JavaScript单线程 在上篇博客<Promise的前世今生和妙用技巧>的开篇中,我们曾简述了JavaScript的单线程机制和浏览器的事件模型.应很多网友的回复,在这篇文章中将继续展 ...

  4. Design Patterns Simplified - Part 3 (Simple Factory)【设计模式简述--第三部分(简单工厂)】

    原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part3-factory/ Design ...

  5. Android网络定位服务定制简述

    Android 添加高德或百度网络定位服务 Android的网络定位服务以第三方的APK方式提供服务,由于在国内Android原生自带的com.google.android.gms服务几乎处于不可用状 ...

  6. 《Entity Framework 6 Recipes》翻译系列 (1) -----第一章 开始使用实体框架之历史和框架简述

    微软的Entity Framework 受到越来越多人的关注和使用,Entity Framework7.0版本也即将发行.虽然已经开源,可遗憾的是,国内没有关于它的书籍,更不用说好书了,可能是因为EF ...

  7. 简述ASP.NET MVC原理

    1.为什么ASP.NET需要MVC? 因为随着网站的的数量级越来越大,原始的网站方式,这里指的是WebForm,在运行速度和维护性方面,以及代码量上面,越来越难以满足日益庞大的网站维护成本.代码的重构 ...

  8. Design Patterns Simplified - Part 2 (Singleton)【设计模式简述--第二部分(单例模式)】

    原文链接: http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part-2-singleton/ De ...

  9. 【翻译】设计模式学习系列1---【Design Patterns Simplified: Part 1【设计模式简述:第一部分】】

    原文链接:http://www.c-sharpcorner.com/UploadFile/19b1bd/design-patterns-simplified-part1/ Design Pattern ...

  10. Android开发3:Intent、Bundle的使用和ListView的应用 、RelativeLayout(相对布局)简述(简单通讯录的实现)

    前言 啦啦啦~博主又来骚扰大家啦~大家是不是感觉上次的Android开发博文有点长呢~主要是因为博主也是小白,在做实验的过程中查询了很多很多概念,努力去理解每一个知识点,才完成了最终的实验.还有就是随 ...

随机推荐

  1. GitHub 如何忽略文件或者文件夹

    在我们开发项目的时候,往往会产生一些不必要的文件,我们会选择忽略他们,不提交到版本控制中,那我们该如何做呢? 步骤一:在项目根目录下,右键,git bash,在弹出的命令行输入框中输入命令:touch ...

  2. php token验证范例

    <?php $module = $_GET['module']; $action = $_GET['action']; $token = md5sum($module.date('Y-m-d', ...

  3. Inno setup: check for new updates

    Since you've decided to use a common version string pattern, you'll need a function which will parse ...

  4. Nginx四层代理

    Nginx支持四层代理 http://nginx.org/en/docs/stream/ngx_stream_core_module.html 该ngx_stream_core_module模块自1. ...

  5. 基于NFS共享存储实现KVM虚拟机动态迁移

    基于NFS共享存储实现KVM虚拟机动态迁移 一:配置环境 二:安装相关的依赖包 三:实现NFS共享存储 四:KVM机配置相同的步骤 五:安装KVM01安装虚拟机 六:实现迁移  实验初始配置:所有主机 ...

  6. office 365 激活

    将以下代码复制到记事本 @echo off title Activate Microsoft Office ALL versions &echo - Microsoft Office Prof ...

  7. 《Python游戏编程快速上手》——1.3 如何使用本书

    本节书摘来自异步社区<Python游戏编程快速上手>一书中的第1章,第1.3节,作者[美] Al Sweigart(斯维加特),李强 译,更多章节内容可以访问云栖社区"异步社区& ...

  8. 基于国内某云的 Domain Fronting 技术实践

    发布时间:2019-12-16 11:30:53 一.简介 Domain Fronting,中文译名 “域前置” 或 “域名前置”,是一种用于隐藏真实C2服务器IP且同时能伪装为与高信誉域名通信的技术 ...

  9. 实现MapReduce

    简介 当我们要统计数亿文本的词频,单个机器性能一般,况且是数亿级数据,处理是十分缓慢的,对于这样的任务,希望的是多台电脑共同处理,大幅度减少任务时间.联合多台电脑一起工作的系统就是分布式系统. 最近在 ...

  10. spark系列-7、spark调优

    官网说明:http://spark.apache.org/docs/2.1.1/tuning.html#data-serialization 一.JVM调优 1.1.Java虚拟机垃圾回收调优的背景 ...