P5782 和平委员会 题解
题目分析
2 - SAT 板子题是这样的:
给 n 个节点, m 个类似 ¬ a ∨ b \lnot a \lor b ¬a∨b (满足 a ← f a l s e a \gets false a←false 或者 b ← t r u e b \gets true b←true)的条件,求是否能给 n 个节点赋值,使其满足那 m 个条件。
此题概述:
此题与模板题的不同在于:
-
一党派的 2 名代表的编号是连续的;
-
相互排斥的 2 名代表不能同时存在于委员会(建图)。
求解方法:
(若您对 2 - SAT 没有学习、接触过,请您先做做 P4782 2 - SAT 模板 。)
-
编号连续:
当一党派中的两个代表标号连续时,我们想通过第 i 名代表的编号找到另一名代表的编号就不像直接找 i + n i+n i+n 那么简单了。
啊这个也简单。我们写一个函数:判断当前编号 x 奇偶性,若 x 为奇数,另一名的编号为 x+1 ;反之,另一名的编号为 x-1 。
-
建图:
假设我们现在已知两个党派,其党员分别为 A 、B 以及 C 、D。且已知 A 与 C 有仇,即他们不能同时在委员会中。
那么此时我们将怎么建边呢?
我们建两条有向边:
-
若 C 在委员会中,那么 A 绝对不能再委员会中,又因为题目要求,所以必须让 B 再委员会中;
-
若 A 在委员会中,则只能让 D 在委员会中(理论同上)。
这样的建边原理和模板题一样,但此题的建边明显比模板要简单。
-
-
判断、输出答案:
这点简单,需要注意的是,我们在循环时,只能循环编号为奇数的点或者编号为偶数的点,避免重复(同时这样处理也是较为简单的方式)。
综上,这是这道题的解析 (我废话有点多…)。
代码奉上:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2000005;
int n, m;
int cnt, hd[maxn];
struct node{
int to, nxt;
}e[maxn * 2];
int dfn[maxn], low[maxn], co[maxn];
int tmp, top, col;
int st[maxn];
void add (int u, int v)
{
e[++cnt].nxt = hd[u];
e[cnt].to = v;
hd[u] = cnt;
}
int find (int x)
{
if (x % 2 == 1) return x + 1;
return x - 1;
}
void tarjan (int u)
{
dfn[u] = low[u] = ++tmp;
st[++top] = u;
for (int i = hd[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (!dfn[v])
{
tarjan (v);
low[u] = min (low[u], low[v]);
}
else if (!co[v]) low[u] = min (low[u], dfn[v]);
}
if (dfn[u] == low[u])
{
co[u] = ++col;
while (st[top] != u)
{
co[st[top]] = col;
top--;
}
top--;
}
}
int main ()
{
scanf ("%d %d", &n, &m);
for (int i = 1; i <= m; i++)
{
int a, b;
scanf ("%d %d", &a, &b);
add (a, find (b));
add (b, find (a));
}
for (int i = 1; i <= n * 2; i++)
{
if (!dfn[i]) tarjan (i);
}
for (int i = 1; i <= n; i += 2)
{
if (co[i] == co[i + 1])
{
printf ("NIE\n");
return 0;
}
}
for (int i = 1; i <= 2 * n; i += 2)
{
if (co[i] <= co[i + 1]) printf ("%d\n", i);
else printf ("%d\n", i + 1);
}
printf ("\n");
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话