【图论】2-SAT

这篇具有很好参考价值的文章主要介绍了【图论】2-SAT。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考资料:2-SAT学习笔记

什么是2-SAT问题呢?

(¬a∨b∨¬c)∧(a∨b∨¬c)∧(¬a∨¬b∨c),给出一个类似于这样的式子,让你找出满足条件的一个解,这样的问题就是SAT问题,因为每一个括号内都有三个被限制的变量,所以这叫做3-SAT问题(是因为括号内的变量数有3个才叫3-SAT,不是因为abc才叫3-SAT)

所以2-SAT也很好理解,(¬a∨b)∧(a∨c)∧(¬c∨¬b)就叫做 2-SAT 问题

可以证明 3-SAT 及以上的问题只能用暴力枚举解决(我也不知道怎么证明),所以我们只讨论2-SAT问题

理论知识

前置知识,你需要学会【图论】有向图的强连通分量

我们将 a V b 理解成:选择了a就不能选b,选择了b就不能选aa b必须要选择一个

那我们就可以得到这样的关系:选择了a就要选择¬b, 选择了b就要选择¬a,反之也成立

根据这个关系建图,我们可以得到

【图论】2-SAT,图论,图论

我们可以看出,所有在一个强连通分量里的元素是等价的

因此,建好图之后,只要出现 x¬x 在一个强连通分量里,就说明它们等价,也就出现了矛盾,无解

接下来是一道洛谷的模板题

例题

P4782 【模板】2-SAT

题目链接

题目描述

n n n 个布尔变量 x 1 x_1 x1 ∼ \sim x n x_n xn,另有 m m m 个需要满足的条件,每个条件的形式都是 「 x i x_i xitrue / false x j x_j xjtrue / false」。比如 「 x 1 x_1 x1 为真或 x 3 x_3 x3 为假」、「 x 7 x_7 x7 为假或 x 2 x_2 x2 为假」。

2-SAT 问题的目标是给每个变量赋值使得所有条件得到满足。

输入格式

第一行两个整数 n n n m m m,意义如题面所述。

接下来 m m m 行每行 4 4 4 个整数 i i i, a a a, j j j, b b b,表示 「 x i x_i xi a a a x j x_j xj b b b」( a , b ∈ { 0 , 1 } a, b\in \{0,1\} a,b{0,1})

输出格式

如无解,输出 IMPOSSIBLE;否则输出 POSSIBLE

下一行 n n n 个整数 x 1 ∼ x n x_1\sim x_n x1xn x i ∈ { 0 , 1 } x_i\in\{0,1\} xi{0,1}),表示构造出的解。

样例输入 #1

3 1
1 1 3 0

样例输出 #1

POSSIBLE
0 0 0

提示

1 ≤ n , m ≤ 1 0 6 1\leq n, m\leq 10^6 1n,m106 , 前 3 3 3 个点卡小错误,后面 5 5 5 个点卡效率。

由于数据随机生成,可能会含有( 10 0 10 0)之类的坑,但按照最常规写法的写的标程没有出错,各个数据点卡什么的提示在标程里。

code文章来源地址https://www.toymoban.com/news/detail-827295.html

#include <bits/stdc++.h>

using namespace std;

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);

	int n, m;
	cin >> n >> m;

	vector<vector<int>> g(2 * n + 1);
	for (int i = 1; i <= m; i ++ )
	{
		int a, va, b, vb;
		cin >> a >> va >> b >> vb;
		g[a + !va * n].push_back(b + vb * n);
		g[b + !vb * n].push_back(a + va * n);
		// 下面四行和上两行等价
		// if (va && vb) g[a].push_back(b + n), g[b].push_back(a + n);
		// else if (va && !vb) g[a].push_back(b), g[b + n].push_back(a + n);
		// else if (!va && vb) g[a + n].push_back(b + n), g[b].push_back(a);
		// else if (!va && !vb) g[a + n].push_back(b), g[b + n].push_back(a);
	}

	vector<int> dfn(2 * n + 1), low(2 * n + 1), id(2 * n + 1);
	vector<bool> in_stk(2 * n + 1);
	int timestamp = 0, scc_cnt = 0;
	stack<int> stk;

	function<void(int)> tarjan = [&](int u)
	{
    	dfn[u] = low[u] = ++ timestamp; // 先将dfn和low都初始化为时间戳
    	stk.push(u), in_stk[u] = true; // u加入栈中

    	for (int i = 0; i < g[u].size(); i ++ )
    	{
    	    int j = g[u][i]; // 取出u的所有邻点j
    	    if (!dfn[j]) // 如果j还没被遍历
    	    {
    	        tarjan(j);
    	        low[u] = min(low[u], low[j]); // 用low[j]更新low[u]
    	    }
    	    else if (in_stk[j]) low[u] = min(low[u], dfn[j]); // 如果j已入栈 则用dfn[j]更新low[u]
    	}

    	if (dfn[u] == low[u]) // 如果该点是所在强连通分量的最高点
    	{
    	    ++ scc_cnt; // 强连通分量数量加一
    	    int y;
    	    do {
    	        y = stk.top(); // 取出栈顶元素
    	        stk.pop();
    	        in_stk[y] = false;

    	        id[y] = scc_cnt; // 标记每个点所在的连通分量编号
    	    } while (y != u); // 直到取到此连通分量的最高点为止
    	}
	};

	for (int i = 1; i <= 2 * n; i ++ )
		if (!dfn[i]) tarjan(i);

	for (int i = 1; i <= n; i ++ )
		if (id[i] == id[i + n])
		{
			cout << "IMPOSSIBLE\n";
			return 0;
		}
	
	cout << "POSSIBLE\n";
	for (int i = 1; i <= n; i ++ )
		if (id[i] > id[i + n]) cout << 1 << ' ';
		else cout << 0 << ' ';
	cout << '\n';
}

到了这里,关于【图论】2-SAT的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 「SAP ABAP」OPEN SQL(九)【SAT事务码】

    💂 作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言ABAP,SQL进行任务的完成,对SAP企业管理系统,SAP ABAP开发和数据库具有较

    2023年04月13日
    浏览(37)
  • Sat-Hacking(2):Starlink卫星通信频段

    了解卫星通信频段是学习卫星安全的基础理论知识,卫星通信频段是指用于卫星通信的无线电波频谱范围。在卫星通信中,无线电波在地面站与卫星之间传输信息,实现通信和数据传输。为了使各种卫星和地面系统之间的通信有效且互不干扰,国际电信联盟(ITU)将频谱划分

    2024年02月06日
    浏览(27)
  • Sat-Hacking(4):Starlink路由器逆向分析-上篇

    在本篇文章中,我们将探讨 SpaceX Starlink 路由器的逆向分析过程。Starlink 是 SpaceX 推出的一项革命性的卫星互联网服务,旨在为全球偏远地区提供高速、低延迟的互联网连接。为了实现这一目标,Starlink 需要一个高性能的路由器来管理用户的互联网连接。逆向分析这种设备对于

    2024年02月10日
    浏览(37)
  • 「ABAP」万字详解,一文带你入门SAT事务码【SQL优化必备】

    💂 作者简介: THUNDER王,一名热爱财税和SAP ABAP编程以及热爱分享的博主。目前于江西师范大学本科在读,同时任汉硕云(广东)科技有限公司ABAP开发顾问。在学习工作中,我通常使用偏后端的开发语言ABAP,SQL进行任务的完成,对SAP企业管理系统,SAP ABAP开发和数据库具有较

    2023年04月09日
    浏览(50)
  • 有趣的Hack-A-Sat黑掉卫星挑战赛——跟踪卫星

    国家太空安全是国家安全在空间领域的表现。随着太空技术在政治、经济、军事、文化等各个领域的应用不断增加,太空已经成为国家赖以生存与发展的命脉之一,凝聚着巨大的国家利益,太空安全的重要性日益凸显[1]。而在信息化时代,太空安全与信息安全紧密地结合在一

    2024年02月12日
    浏览(75)
  • 有趣的Hack-A-Sat黑掉卫星挑战赛——被破坏的阿波罗计算机(解法二)

    国家太空安全是国家安全在空间领域的表现。随着太空技术在政治、经济、军事、文化等各个领域的应用不断增加,太空已经成为国家赖以生存与发展的命脉之一,凝聚着巨大的国家利益,太空安全的重要性日益凸显[1]。而在信息化时代,太空安全与信息安全紧密地结合在一

    2023年04月22日
    浏览(34)
  • 【C++算法竞赛 · 图论】图论基础

    前言 图论基础 图的相关概念 图的定义 图的分类 按数量分类: 按边的类型分类: 边权 简单图 度 路径 连通 无向图 有向图 图的存储 方法概述 代码 复杂度 图论(Graph theory) ,是 OI 中的一样很大的一个模块,围绕它有很多高难度的算法以及高级的概念。 这篇文章将介绍关

    2024年04月12日
    浏览(33)
  • 图论与算法(1)图论概念

    在计算机科学中,图论与算法是两个重要且紧密相关的领域。图论研究图的性质和特征,而算法设计和分析解决问题的方法和步骤。图论提供了一种形式化的方法来描述和分析各种关系和连接,而算法则为解决图相关的问题提供了有效的解决方案。 图论是研究图的结构和性质

    2024年02月07日
    浏览(30)
  • c++图论免费ppt,简单深度理解图论

    本篇博文想分享一个ppt,是帮助大家简单深度理解c++图论. 作者承诺:分享的东西没有病毒,是资料。 分享的东西一个是ppt,ppt里面是150页的,里面将带领大家简单深度理解c++图论,还有一个就是里面例题的数据,大家可以按照数据与例题自己练练! 分享的东西免费!免费!免

    2024年02月10日
    浏览(27)
  • 什么是图论和图论在数字图像中的应用

    图论是数学中的一个分支,研究由节点和边组成的图的性质和关系。在计算机科学中,图论广泛应用于网络分析、图像分割、社交网络分析、路由算法、搜索算法等领域。 图由一组节点和一组边组成,节点可以表示各种实体,如人、物、事件等,边则表示它们之间的关系。节

    2024年01月23日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包