P5782 和平委员会 题解

P5782 和平委员会 - 传送门

题目分析

2 - SAT 板子题是这样的:

给 n 个节点, m 个类似 ¬ a ∨ b \lnot a \lor b ¬ab (满足 a ← f a l s e a \gets false afalse 或者 b ← t r u e b \gets true btrue)的条件,求是否能给 n 个节点赋值,使其满足那 m 个条件。

此题概述:

此题与模板题的不同在于:

  1. 一党派的 2 名代表的编号是连续的;

  2. 相互排斥的 2 名代表不能同时存在于委员会(建图)。

求解方法:

(若您对 2 - SAT 没有学习、接触过,请您先做做 P4782 2 - SAT 模板 。)

  1. 编号连续:

    当一党派中的两个代表标号连续时,我们想通过第 i 名代表的编号找到另一名代表的编号就不像直接找 i + n i+n i+n 那么简单了。

    啊这个也简单。 我们写一个函数:

    判断当前编号 x 奇偶性,若 x 为奇数,另一名的编号为 x+1 ;反之,另一名的编号为 x-1 。

  2. 建图:

    假设我们现在已知两个党派,其党员分别为 A 、B 以及 C 、D。且已知 A 与 C 有仇,即他们不能同时在委员会中。

    那么此时我们将怎么建边呢?

    我们建两条有向边:

    • 若 C 在委员会中,那么 A 绝对不能再委员会中,又因为题目要求,所以必须让 B 再委员会中;

    • 若 A 在委员会中,则只能让 D 在委员会中(理论同上)。

    这样的建边原理和模板题一样,但此题的建边明显比模板要简单。

  3. 判断、输出答案:

    这点简单,需要注意的是,我们在循环时,只能循环编号为奇数的点或者编号为偶数的点,避免重复(同时这样处理也是较为简单的方式)。


综上,这是这道题的解析 (我废话有点多…)

代码奉上:

#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;
}
posted @   pldzy  阅读(44)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示