问题简述

有 \(n\) 个变量,每个变量可赋为 \(1\) 或 \(0\)

必须满足一些限制条件,如“ \(a\) 为1 或 \(b\) 为0 ” “ \(a\) 为0 且 \(b\) 为1” …

判断是否有一种赋值方法满足所有限制条件,并构造答案。

做法

首先拆点,把每个变量 \(i\) 拆成 \(i\) 选1 和 \(i\) 选0 两个点,在这两个点中选出一个

现在我们在 \(2n\) 个点中选出了 \(n\) 个点,相当于选择了一种赋值方案

换句话说,每种赋值方案就是在 每对 \(i\) 选1 和 \(i\) 选0 中选一个点

考虑所有限制条件,有两种类型。

第一种是 “ \(x_i=k_i\) 且 \(x_j=k_j\) ”

我们可以连一些有向边 \((u,v)\),表示如果选了 \(u\) ,就一定要选 \(v\)

那针对这种情况,则要连 \((x_i选k_i, x_j选k_j)\)

但这样还不够!

回忆一下“逆否命题”,我们还需连 \((x_j不选k_j,x_i不选k_i)\) 才可保证限制满足。

第二种是 “ \(x_i=k_i\) 或 \(x_j=k_j\) ”

连边 \((x_i不选k_i, x_j选k_j)\) 和 \((x_j不选k_j,x_i选k_i)\)

这样下来,我们发现连的所有边是对称的!(真命题&逆否命题嘛)

接下来,我们对这个有向图跑强连通分量缩点。

对每个强连通分量,要么都选,要么都不选。

还记得如何选赋值方案吗?

每对\(i\) 选1 和 \(i\) 选0 中只能选1个,那么判断一下,如果这两个点在同一个强连通分量中,则无解。

如果不在,选拓扑排序中拓扑序靠后的那个点,(也就是 \(tarjan\) 中编号较小的那个点),可以保证这样选出的点是一组合理的赋值方案。

代码

洛谷模板题 \(P4782\)

#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; const int N = 2000005; struct node{
int v;
node *nxt;
}pool[N],*h[N];
int cnt;
void addedge(int u,int v){
node *p=&pool[++cnt];
p->v=v;p->nxt=h[u];h[u]=p;
} int n,m; int tot;
int dfn[N],low[N],scc,belong[N];
int st[N],top,vis[N];
void tarjan(int u){
int v;
dfn[u]=low[u]=++tot;
vis[u]=1;
st[top++]=u;
for(node *p=h[u];p;p=p->nxt)
if(!dfn[v=p->v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(vis[v]) low[u]=min(low[u],dfn[v]);
if(low[u]==dfn[u]){
scc++;
while(1){
belong[st[--top]]=scc;
vis[st[top]]=0;
if(st[top]==u) break;
}
}
} int main()
{
int a,b,c,d;
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++){
scanf("%d%d%d%d",&a,&b,&c,&d);
addedge(a+(1-b)*n,c+d*n);
addedge(c+(1-d)*n,a+b*n);
} for(int i=1;i<=2*n;i++)
if(!dfn[i]) tarjan(i); int flag=0;
for(int i=1;i<=n;i++)
if(belong[i]==belong[i+n]) flag=1;
if(flag) { printf("IMPOSSIBLE\n"); return 0; }
printf("POSSIBLE\n%d",belong[1]>belong[n+1]);
for(int i=2;i<=n;i++) printf(" %d",belong[i]>belong[n+i]); return 0;
}

【模板】2-SAT问题的更多相关文章

  1. 2 - sat 模板(自用)

    2-sat一个变量两种状态符合条件的状态建边找强连通,两两成立1 - n 为第一状态(n + 1) - (n + n) 为第二状态 例题模板 链接一  POJ 3207 Ikki's Story IV ...

  2. TwoSAT算法模板

    该模板来自大白书 [解释] 给多个语句,每个语句为“ Xi为真(假) 或者 Xj为真(假)” 每个变量和拆成两个点 2*i为假, 2*i+1为真 “Xi为真 或 Xj为真”  等价于 “Xi为假 –& ...

  3. C++ 模板基础

    我们学习使用C++,肯定都要了解模板这个概念.就我自己的理解,模板其实就是为复用而生,模板就是实现代码复用机制的一种工具,它可以实现类型参数化,即把类型定义为参数:进而实现了真正的代码可重用性.模版可 ...

  4. (模板)poj2947(高斯消元法解同余方程组)

    题目链接:https://vjudge.net/problem/POJ-2947 题意:转换题意后就是已知m个同余方程,求n个变量. 思路: 值得学习的是这个模板里消元用到lcm的那一块.注意题目输出 ...

  5. 虚拟化技术之kvm镜像模板制作工具virt-sysprep

    virt-sysprep这个工具来自libguest-tools这个工具包,它能够把kvm虚拟机对应的磁盘文件做成一个模板,后续我们启动虚拟机就可以基于这个镜像模板启动:什么是镜像模板呢?所谓模板就是 ...

  6. Jade模板引擎让你飞

    写在前面:现在jade改名成pug了 一.安装 npm install jade 二.基本使用 1.简单使用 p hello jade! 渲染后: <p>hello jade!</p ...

  7. ABP入门系列(2)——通过模板创建MAP版本项目

    一.从官网创建模板项目 进入官网下载模板项目 依次按下图选择: 输入验证码开始下载 下载提示: 二.启动项目 使用VS2015打开项目,还原Nuget包: 设置以Web结尾的项目,设置为启动项目: 打 ...

  8. CMS模板应用调研问卷

    截止目前,已经有数十家网站与我们合作,进行了MIP化改造,在搜索结果页也能看到"闪电标"的出现.除了改造方面的问题,MIP项目组被问到最多的就是:我用了wordpress,我用了织 ...

  9. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  10. 【原创分享·微信支付】C# MVC 微信支付之微信模板消息推送

    微信支付之微信模板消息推送                    今天我要跟大家分享的是“模板消息”的推送,这玩意呢,你说用途嘛,那还是真真的牛逼呐.原因在哪?就是因为它是依赖微信生存的呀,所以他能不 ...

随机推荐

  1. ajaxSetup()方法

    使用ajaxSetup()方法设置全局Ajax默认选项 使用ajaxSetup()方法可以设置Ajax请求的一些全局性选项值,设置完成后,后面的Ajax请求将不需要再添加这些选项值,它的调用格式为: ...

  2. Crazy Binary String<Map法>

    #include<cstdio> #include<iostream> #include<map> using namespace std; map<int, ...

  3. FineReport报表和水晶报表的比较

    FineReport报表和水晶报表的比较 FineReport报表软件针对复杂格式的报表数据及Web报表的展现,通过多源分片.不规则分组.双向扩展来轻松拖拽做复杂格式的报表,制作报表从此摆脱了复杂的S ...

  4. SPOJ Another Longest Increasing Subsequence Problem 三维最长链

    SPOJ Another Longest Increasing Subsequence Problem 传送门:https://www.spoj.com/problems/LIS2/en/ 题意: 给 ...

  5. k8s数据持久化实验

    Step 1:创建PV ============================================ apiVersion: v1kind: PersistentVolumemetadat ...

  6. 记一次手工清除挖矿病毒WannaMine V4.0的经历

    [作者:byeyear    邮箱:byeyear@hotmail.com    转载请注明] 前两天公司信息安全处通知我的计算机存在永恒之蓝漏洞并已被病毒感染,使用多方杀软及专杀工具均无法有效清除, ...

  7. Delphi XE里的StrPas要注意哦(要让StrPas知道哪里是字符串结束)

    废话不多说了,直接上例子解说: procedure TForm1.Button1Click(Sender: TObject);var  aa: array[0..1]of AnsiChar;  bb1 ...

  8. 嗨,让我带你逐行剖析Vue.js源码

    本项目受到了阮一峰老师的肯定,已刊登在阮一峰老师微信公众号的科技爱好者周刊第87期,同时也被多个微博大V转发,短短一个月时间内在github上star数量就已经突破2k! Hello,大家好,我最近在 ...

  9. 【一起学源码-微服务】Nexflix Eureka 源码四:EurekaServer启动之完成上下文构建及EurekaServer总结

    前言 上篇文章已经介绍了 Eureka Server上下文创建相关的Eureka Client逻辑,这一部分还是比较复杂的.接下来就讲解下Eureka Server上下文初始化最后的部分,然后加上整个 ...

  10. 【C++】递归 课后习题3-13、3-14

    // // main.cpp // 3-13递归Fibonacci级数 // // Created by T.P on 2018/3/21. // Copyright © 2018年 T.P. All ...