2402. 2-SAT 问题(tarjan,2-SAT模板题)

活动 - AcWing

给定 n 个还未赋值的布尔变量 x1∼xn。

现在有 m 个条件,每个条件的形式为 “xi 为 0/1  xj 为 0/1 至少有一项成立”,例如 “x1 为 1 或 x3 为 0”、“x8 为 0 或 x4 为 0” 等。

现在,请你对这 n 个布尔变量进行赋值(0 或 1),使得所有 m 个条件能够成立。

输入格式

第一行包含两个整数 n,m。

接下来 m 行,每行包含四个整数 i,a,j,b,用来描述一个条件,表示 “xi 为 a 或 xj 为 b”。

输出格式

如果问题有解,则第一行输出 POSSIBLE,第二行输出 n 个整数表示赋值后的 n 个变量 x1∼xn 的值(0 或 1),整数之间用单个空格隔开。

如果问题无解,则输出一行 IMPOSSIBLE 即可。

如果答案不唯一,则输出任意一种正确答案即可。

数据范围

1≤n,m≤106,
1≤i,j≤n,
0≤a,b≤1

输入样例:
3 2
1 1 3 1
2 0 3 0
输出样例:
POSSIBLE
1 1 0

解析: 

该文件无法打开 - AcWing

2-SAT 通常解决这样一类问题:给出若干个这样的命题 x1∼xn,给出一些条件 xi∪xj,即 xi 或 xj 为真,给所有的命题判断真假

首先,有如下等价关系:x∪y⇔¬x→y⇔¬y→x,则将 x 和 ¬x 看成两个不同的节点,将 ¬x 向 y
 连边,¬y 向 x 连边
,即如果 ¬x 为真的话 y 也必须为真,¬y 为真的话 x 也必须为真,则这样的关系依赖图显然会形成一个有向图,将该有向图缩点后,在一个强连通分量内判断是否存在这样一条 x→¬x,即如果 x 为真的话 ¬x 也必然为真,显然矛盾,即整个命题无解,否则 是否一定有解

用 Tarjan 算法求强联通分量,检查是否存在 i 和 i + N 在同一个强连通分量即可。本题还需要输出方案。

这里给出 2-SAT 合法方案的两种构造方法。

第一种构造方法

首先,在一个强连通分量中,只要确定了一个变量的赋值,该强连通分量内其他变量的赋值也就直接确定了,
这启发我们考虑缩点,其次,因为互为逆否命题的有向边在图中成对出现,所以一个零出度点对面的点一定有出边。
选择一个有出边的店会使得该边指向的点必须也被选择,而选择一个零出度点则不会对其他任何点造出影响。

根据上述讨论,第一种构造方法的基本思想就是:自底向上执行拓扑排序,不断尝试选择零出度点。

1. 把强连通分量缩点,因为一般的拓扑排序是自顶向下根据入度进行的,所以我们建立一张缩点后的反图,具体来说:
    (1) 图上每个点都对应原图的强连通分量
    (2) 原图中的边 (x, y) 转化为新图中的边 (c[y], c[x]),其中 c[x] != c[y],c[x] 表示节点 x 所在的强连通分量
    (3) 对于原图中每个点 x,c[x] 和 c[x + N] 新图中两个对称的节点。
2. 在上述反图上统计每个点的入度,执行拓扑排序

    设val[k] 表示原图 k 号强连通分量的赋值标记,初始值为 -1

    从队头每取出一个节点 k (k 相当于原图中一个强连通分量的编号),就检查 k 的赋值标记,若 val[k] = -1 (尚未确定赋值),
    就令 val[k] = 0, val[k + N] = 1,随后把它能到达的点的入度减 1 (拓扑排序的正常过程)

3. 拓扑排序结束之后,就得到最终的答案,对于原图每个节点 i:
    若 val[c[i]] = 0,则变量 x[i] 应赋值为 x[i][0]
    若 val[c[i]] = 1,则变量 x[i] 应赋值为 x[i][1]

第二种构造方法

第二种构造方法是基于第一种构造方法的基础上,进一步利用了 Tarjan 算法对强连通分量编号的特殊性质,使得构造过程更简洁。
可以发现 Tarjan 算法的本质是一次 dfs,它在回溯时会先取出有向图底部的强连通分量进行标记,所以 Tarjan 算法得到的强连
通分量编号本身就已经满足缩点后有向无环图中自底向上的顺序,序列 1, 2, ..., cnt 就是缩点后的反图的拓扑序,无需进行拓
扑排序。

因此,直接比较节点所在的强连通分量的编号大小,即可确定对应变量的赋值 val[i],c[i] 和 c[i + N] 哪个小,就表示哪个会
先被遍历到,先被遍历到的是取值为 0,后被遍历到的取值为 1。

最终,同样的枚举一遍所有节点,根据 val[i] 来确定每个节点的值。

注:构造方法2 其实等于是 构造方法1 的升级版

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
#include<unordered_set>
#include<bitset>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
const int N = 2e6+10, M = 2e6+ 10, INF = 0x3f3f3f3f;
int n, m;
int h[N], e[M], ne[M], idx;
int dfn[N], low[N], ts;
int stk[N], top;
bool in_stk[N];
int id[N],cnt;void add(int a, int b) {e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}int tarjan(int u) {dfn[u] = low[u] = ++ts;stk[++top] = u, in_stk[u] = 1;for (int i = h[u]; i != -1; i = ne[i]) {int j = e[i];if (!dfn[j]) {tarjan(j);low[u] = min(low[u], low[j]);}else if (in_stk[j]) {low[u] = min(low[u], dfn[j]);}}if (dfn[u] == low[u]) {int y;cnt++;do {y = stk[top--];in_stk[y] = 0;id[y] = cnt;} while (y != u);}
}int main() {cin >> n >> m;memset(h, -1, sizeof h);for (int i = 1,x,a,y,b; i <= m; i++) {scanf("%d%d%d%d", &x, &a, &y, &b);x--, y -- ;add(2 * x + !a, 2 * y + b);add(2 * y + !b, 2 * x + a);}for (int i = 0; i < 2 * n; i++) {if (!dfn[i])tarjan(i);}for (int i = 0; i < n; i++) {if (id[i * 2] == id[2 * i + 1]) {cout << "IMPOSSIBLE" << endl;return 0;}}cout << "POSSIBLE" << endl;for (int i = 0; i < n; i++) {if (id[i * 2] < id[i * 2 + 1])printf("0 ");else printf("1 ");}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/732232.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

acwing算法提高之数据结构--树状数组

目录 1 专题介绍2 训练 1 专题介绍 本专题用来汇总使用树状数组算法求解的题目。 应用场景&#xff1a;给你长度为n的数组nums&#xff0c;可以改变第i个数的大小&#xff0c;求数组下标区间[left, right]内的前缀和。要求时间复杂度不超过 O ( l o g N ) O(logN) O(logN)。 …

使用 MySQL 实现 Java 版的 hashCode 函数

前提 MySQL 数据库的编码需要设置为 utf8 或 utf8mb4&#xff0c;因为下面给出的代码是以用 utf8 编码储存数据为前提的。 MySQL Function drop function if exists utf8_unicode; create function utf8_unicode(str varchar(1)) returns bigint begindeclare num_utf8 bigi…

【GB28181】SIP协议实践之Windows下VS2019编译eXosip、osip,测试(附工程源码,一键打开编译)

引言 SIP开源库或者GB28181,这里选择了osip和eXosip,但是这两个库的编译使用有些麻烦,源码下来之后编译会出现很多问题,网上也没有找到完整的编译介绍,只能一步一步的找办法解决,以下帮大家整理编译过程。 如果不想编译,可以跳转文章末尾链接直接下载相应工程直接编译即…

登录校验认证

会话技术 会话&#xff1a;用户打开浏览器&#xff0c;访问web服务器的资源&#xff0c;会话建立&#xff0c;直到有一方断开连接&#xff0c;会话结束。在一次会话中可以包含多次请求和响应。 会话跟踪&#xff1a; 一种维护浏览器状态的方法&#xff0c;服务器需要识别多次请…

Aop注解+Redis解决SpringBoot接口幂等性(源码自取)

目录 一、什么是幂等性&#xff1f; 二、哪些请求天生就是幂等的&#xff1f; 三、为什么需要幂等 1.超时重试 2.异步回调 3.消息队列 四、实现幂等的关键因素 关键因素1 关键因素2 五、引入幂等性后对系统的影响 六、Restful API 接口的幂等性 实战Aop注解redis解…

计算机网络——计算机网络的性能

计算机网络——计算机网络的性能 速率带宽吞吐量时延时延宽带积往返时间RTT利用率信道利用率网络利用率 我们今天来看看计算机网络的性能。 速率 速率这个很简单&#xff0c;就是数据的传送速率&#xff0c;也称为数据率&#xff0c;或者比特率&#xff0c;单位为bit/s&#…

神经网络 梯度与神经元参数w、b关系;梯度与导数关系

参考&#xff1a;https://blog.csdn.net/weixin_44259490/article/details/90295146 视频&#xff1a;https://www.bilibili.com/video/BV1a14y167vh 概念 梯度与w的关系可以用梯度下降公式来表示&#xff1a;ww−α ∂ c o s t ∂ w \frac{\partial cost}{\partial w} ∂w∂…

vs创建asp.net core webapi发布到ISS服务器

打开服务器创建test123文件夹&#xff0c;并设置共享。 ISS配置信息&#xff1a; 邮件网站&#xff0c;添加网站 webapi asp.net core发布到ISS服务器网页无法打开解决方法 点击ISS Express测试&#xff0c;可以成功打开网页。 点击生成&#xff0c;发布到服务器 找到服务器IP…

idm对比aria2哪个好 aria2和idm哪个快 Aria2和IDM的原理

一、idm对比aria2哪个好 下面对aria2和idm进行对比&#xff0c;看看哪款更好。 idm: 优势&#xff1a; 1&#xff09;可将下载速度提升5倍以上&#xff1b; 2&#xff09;界面友好&#xff0c;操作简便&#xff1b; 3&#xff09;支持多个主流的浏览器&#xff1b; 4&am…

基于Vue的娱讯移动端APP前端设计与实现

目 录 摘 要 Abstract 引 言 1绪论 1.1课题背景及目的 1.1.1移动端APP发展简介 3 1.1.2移动端APP的优势 3 1.2前端开发相关技术 1.2.1前端开发工具介绍 3 1.2.2 前端开发相关技术介绍 4 1.3本章小结 2系统分析 2.1功能需求分析 2.2系统工作流程 2.3本章小结 3系统设…

自研cloud框架专题–通用cache模块(五)

通用cache模块 项目特点1.保留原框架的集成&#xff0c;扩展&#xff0c;配置能力2.对于spring-cache增强1.引入核心依赖2.开启多cache配置2.自选缓存pom依赖 二:使用示例1.api示例2.注解示例三:配置说明1.REDISSON_LOCAL_MAP2.REDISSON_2PC 开源地址:https://github.com/28928…

【论文阅读】Segment Anything论文梳理

Abstract 我们介绍了Segment Anything&#xff08;SA&#xff09;项目&#xff1a;新的图像分割任务、模型和数据集。高效的数据循环采集&#xff0c;使我们建立了迄今为止最大的分割数据集&#xff0c;在1100万张图像中&#xff0c;共超过10亿个掩码。 该模型被设计和训练为可…

一例APC注入型病毒分析

概述 这个病毒通过可移动存储介质传播&#xff0c;使用了应用层APC注入和dga域名技术&#xff0c;整个执行过程分为4个阶段&#xff0c;首先从资源节中解密出一段shellcode和一个PE&#xff0c;执行shellcode&#xff0c;创建一个同名的傀儡进程&#xff0c;将解密出来的PE注入…

多轨迹建模方法的介绍与实操-基于R语言

本文介绍了多轨迹建模方法&#xff08;Group-Based Multivariate Trajectory Modeling&#xff09;&#xff0c;这是一种扩展了单指标组基轨迹建模的技术&#xff0c;用于分析多个疾病生物标志物或临床重要因素的联合轨迹&#xff0c;以更好地理解和追踪疾病进程、行为或健康状…

2024蓝桥杯每日一题(归并排序)

一、第一题&#xff1a;火柴排队 解题思路&#xff1a;归并排序 重点在于想清楚是对哪个数组进行归并排序求逆序对 【Python程序代码】 from math import * n int(input()) a list(map(int,input().split())) b list(map(int,input().split())) na,nb [],[] for …

c++结构体中定义函数方法介绍

在C中&#xff0c;结构体&#xff08;Struct&#xff09;是一种用户自定义的数据类型&#xff0c;用于组织不同数据类型的成员。结构体可以包含变量、常量、函数等&#xff0c;使得数据的组织更加灵活。以下是关于C结构体中函数的介绍&#xff1a; 结构体声明&#xff1a; 在介…

【OpenGL手册12】 统一变量Uniform

OpenGL基础 - 统一变量Uniform 目录 一、说明二、 Uniform变量概念2.1 Uniform变量和特点2.2 Uniform变量定义方法2.3 Uniform变量赋值和传参 三、如何在Shader中自定义Location四、赋值五、统一变量缓冲对象六、赋值函数 一、说明 关于统一变量&#xff0c;也有一系列概念和方…

【嵌入式】字体极限瘦身术:Fontmin在嵌入式UI中的魔法应用(附3500常用汉字)

1. 概述 在嵌入式系统的用户界面&#xff08;UI&#xff09;设计中&#xff0c;字体的选择和优化至关重要。一个恰当的字体不仅能够提升用户体验&#xff0c;还能彰显产品特色。然而&#xff0c;由于嵌入式设备常常受限于存储空间和处理能力&#xff0c;大型字体文件可能成为性…

代码随想录算法训练营第五十五天丨583. 两个字符串的删除操作、72. 编辑距离

583. 两个字符串的删除操作 开窍了 class Solution:def minDistance(self, word1: str, word2: str) -> int:n1, n2 len(word1), len(word2)dp [[0] * (n2 1) for _ in range(n1 1)]for i in range(1, n1 1):dp[i][0] ifor j in range(1, n2 1):dp[0][j] jfor i i…

LeetCode的使用方法

LeetCode的使用方法 一、LeetCode是什么&#xff1f;1.LeetCode简介2.LeetCode官网 二、LeetCode的使用方法1.注册账号2.力扣社区力扣编辑器 2.1 讨论发起讨论参与讨论关注讨论 2.2 文章撰写文章关注文章 3.力扣面试官版测评面试招聘竞赛 4.力扣学习LeetBook 书架我的阅读猜您喜…