闲话 10.10

news/2024/10/10 12:18:56

想到什么写什么


昨晚

CTH(大喊):HDK!

HDK(大喊):CTH!

CTH(愣了一下):干啥?


2-SAT

定义

给出若干个形如 \(a\lor b\) 的限制条件,询问是否有满足条件的一组解。

人话:给出 \(n\) 个集合,每个集合两个元素,再给定若干个限制条件 \(\left \langle a,b\right \rangle\) 表示 \(a\)\(b\) 矛盾,询问在这 \(n\) 个集合中各选一个能否满足所有限制条件。

思路

考虑转化限制条件。已知 \(a\lor b\) 为真,则当 \(\lnot a\) 为真时 \(b\) 必为真,简单推一下可得:

\[\lnot a\to b,\lnot b \to a \]

这样模型就构建出来了,我们可以将其转化成图来做。

考虑这样连边的含义,若起点为真则终点必为真,那么若成环则表示这些点同时为真或假,我们可以用 tarjan 将它们缩成一个点。

判断有无解的办法是看 \(a\)\(\lnot a\) 的点是否缩成同一个点,若是则显然无解,否则有解。

若要输出方案,一种合法的构造是判断 \(a\)\(\lnot a\) 缩点的先后,先缩为真。

实现

【模板】2-SAT

直接按思路做即可。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{char ch = getchar();lx x = 0 , f = 1;for(;ch<'0'||ch>'9';ch = getchar()) if(ch == '-') f = -1;for(;ch>= '0' && ch<= '9';ch = getchar()) x = (x<<3) + (x<<1) + (ch^48);return x*f;
}
#undef lx
#define qr qr()
#define pii pair<int, int>
#define pil pair<int, ll>
#define fi first
#define se second
const int Ratio = 0;
const int N = 2e6 + 5;
int n, m;
int dfn[N], low[N], tot, bl[N], num;
int hh[N], to[N << 1], ne[N << 1], cnt;
stack<int> st;
namespace Wisadel
{void Wadd(int u, int v){to[++cnt] = v;ne[cnt] = hh[u];hh[u] = cnt;}void Wtarjan(int u){dfn[u] = low[u] = ++tot, st.push(u);for(int i = hh[u]; i != -1; i = ne[i]){int v = to[i];if(!dfn[v]){Wtarjan(v);low[u] = min(low[u], low[v]);}else if(!bl[v]) low[u] = min(low[u], dfn[v]);}if(dfn[u] == low[u]){++num;while(st.size()){int zc = st.top(); st.pop();bl[zc] = num;if(zc == u) break;}}}short main(){// freopen(".in", "r", stdin) , freopen(".out", "w", stdout);n = qr, m = qr;memset(hh, -1, sizeof hh);fo(i, 1, m){int x = qr, v1 = qr, y = qr, v2 = qr;if(v1 && v2) Wadd(x + n, y), Wadd(y + n, x);if(v1 && !v2) Wadd(x + n, y + n), Wadd(y, x);if(!v1 && v2) Wadd(x, y), Wadd(y + n, x + n);if(!v1 && !v2) Wadd(x, y + n), Wadd(y, x + n);}fo(i, 1, 2 * n) if(!dfn[i]) Wtarjan(i);bool can = 1;fo(i, 1, n) if(bl[i] == bl[i + n]){can = 0; break;}if(!can) puts("IMPOSSIBLE");else{puts("POSSIBLE");fo(i, 1, n) printf("%d ", (bl[i] < bl[i + n]));}return Ratio;}
}
int main(){return Wisadel::main();}

例题

[JSOI2010] 满汉全席

每一种食材不是满就是汉,比较能看出来是 2-SAT,看出来后就是纯板子了。

点击查看代码
#include<bits/stdc++.h>
#define fo(x, y, z) for(register int (x) = (y); (x) <= (z); (x)++)
#define fu(x, y, z) for(register int (x) = (y); (x) >= (z); (x)--)
using namespace std;
typedef long long ll;
#define lx ll
inline lx qr()
{char ch = getchar();lx x = 0 , f = 1;for(;ch<'0'||ch>'9';ch = getchar()) if(ch == '-') f = -1;for(;ch>= '0' && ch<= '9';ch = getchar()) x = (x<<3) + (x<<1) + (ch^48);return x*f;
}
#undef lx
#define qr qr()
#define pii pair<int, int>
#define pil pair<int, ll>
#define fi first
#define se second
const int Ratio = 0;
const int N = 1e5 + 5;
int m, n;
int dfn[N], low[N], tot, bl[N], num;
int hh[N], to[N << 1], ne[N << 1], cnt;
stack<int> st;
namespace Wisadel
{void Wadd(int u, int v){to[++cnt] = v;ne[cnt] = hh[u];hh[u] = cnt;}void Wtarjan(int u){dfn[u] = low[u] = ++tot, st.push(u);for(int i = hh[u]; i != -1; i = ne[i]){int v = to[i];if(!dfn[v]){Wtarjan(v);low[u] = min(low[u], low[v]);}else if(!bl[v]) low[u] = min(low[u], dfn[v]);}if(dfn[u] == low[u]){num++;while(st.size()){int zc = st.top(); st.pop();bl[zc] = num;if(zc == u) break;}}}short main(){// freopen(".in", "r", stdin) , freopen(".out", "w", stdout);int T = qr;while(T--){n = qr, m = qr;cnt = num = tot = 0;memset(hh, -1, sizeof hh);memset(bl, 0, sizeof bl);memset(dfn, 0, sizeof dfn);fo(i, 1, m){string s1, s2; cin >> s1 >> s2;int l1 = s1.size(), l2 = s2.size();int v1 = 0, v2 = 0;fo(j, 1, l1 - 1) v1 = v1 * 10 + s1[j] - '0';fo(j, 1, l2 - 1) v2 = v2 * 10 + s2[j] - '0';if(s1[0] == 'm' && s2[0] == 'm') Wadd(v1 + n, v2), Wadd(v2 + n, v1);if(s1[0] == 'm' && s2[0] == 'h') Wadd(v1 + n, v2 + n), Wadd(v2, v1);if(s1[0] == 'h' && s2[0] == 'm') Wadd(v1, v2), Wadd(v2 + n, v1 + n);if(s1[0] == 'h' && s2[0] == 'h') Wadd(v1, v2 + n), Wadd(v2, v1 + n);}fo(i, 1, 2 * n) if(!dfn[i]) Wtarjan(i);bool can = 1;fo(i, 1, n) if(bl[i] == bl[i + n]){can = 0; break;}if(!can) puts("BAD");else puts("GOOD");}return Ratio;}
}
int main(){return Wisadel::main();}

发现要用到 tarjan,但是大部分忘了,所以复习。

Tarjan 求点双,缩点

感觉现阶段再看 tarjan 好理解了不少。

\(dfn_u\) 为点 \(u\) 的 dfs 序,\(low_u\) 是点 \(u\) 能通过返祖边返回到的最小的节点的 dfs 序。

后面仙姑。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

唯一客服浏览器插件: 视频号直播自动回复与循环发送话术-自动化插件

唯一客服浏览器插件 gofly.v1kf.com 我们在做视频号直播的时候,会有这种自动回复咨询问题的功能唯一客服浏览器插件现在就支持,在视频号直播后台,自动化回复用户问题,以及循环发送我们的介绍话术 十年开发经验程序员,离职全心创业中,历时三年开发出的产品《唯一客服系统》…

[编程笔记] 当前上下文中不存在名称ViewBag

当前上下文中不存在名称"ViewBag",很多ViewBag、@Html.Partial、@Html.FunctionBar() 等这些地方都报波浪线了,提示不存在这个名称,但是代码是可以运行的最近在弄另外一个项目,很长一段时间没接触MVC了,Visual Studio 2022识别cshtml文件的时候,出了一点故障!…

MSSQL-从字符串转换日期和/或时间时,转换失败

1、报错的sql为: select ID,Test_time as 时间, from ProcessData where convert(datetime,test_time,120) between convert(datetime, 2020-10-10, 120) and convert(datetime, 2024-10-11, 120) 它是将Test_time转化为datetime格式,再用between进行比较; 2、报错原因:…

Pytorch常用代码段汇总

Pytorch常用代码段来源: https://zhuanlan.zhihu.com/p/104019160 PyTorch最好的资料是官方文档。本文是PyTorch常用代码段,在参考资料[1](张皓:PyTorch Cookbook)的基础上做了一些修补,方便使用时查阅。 1. 基本配置 导入包和版本查询 import torch import torch.nn as nn…

manim边学边做--无向图

无向图属于数学中的图论这一学科, 所谓无向图G,就是由顶点集V(非空集合)和边集E(由V中元素构成的无序二元组的集合)组成的图, 可表示为G=(V,E)。 在无向图中,边没有方向,即从顶点A到顶点B的边与从顶点B到顶点A的边是相同的。 无向图简洁直观,常用于描述社交网络,交通…

[持续更新]程序员每天会阅读哪些技术网站(带链接)来提升自己?

本文原文来自[持续更新]程序员每天会阅读哪些技术网站(带链接)来提升自己? 国内的网站 这些国内技术网站和社区涵盖了编程语言、算法、职业规划、云计算、AI等多方面的内容,可以获取最新的技术资讯、学习资源和开发经验。当然目前国内的技术社区的内容还是相当的鱼龙混杂。CS…

VScode远程访问虚拟机

下载vscode插件Remote Development 该插件包括了wsl,remote ssh 等四个插件,均是用于远程访问虚拟机。 通过ssh访问虚拟机 下载后在工具栏索引可以看到如下标识,按顺序点击进入,然后在“3”显示的搜索框通过“ ssh username@ipAddr”访问,这是方法一。 方法二,还可以通…

20222317 2024-2025-1《网络与系统攻防技术》实验一实验报告

一、实验内容 本次实验的对象是一个名为pwn1的linux可执行文件。该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们本次实验将学习两种方…