P10873 [COTS 2022] 帽子 Šeširi 解题报告

解题报告:P10873 [COTS 2022] 帽子 Šeširi

1. 问题分析:我们要解决什么?

想象一下,你和N-1个朋友站成一圈,每个人头上都戴了一顶帽子,颜色非红即白。你看得见所有其他人的帽子,但唯独看不见自己的。现在,你们需要事先商量好一个“万能策略”。这个策略的规则是:当你看到某种特定的N-1顶帽子的组合时,你应该猜自己戴的是什么颜色的帽子。

这个“万能策略”必须非常厉害,要保证无论老天爷给你们分配了怎样的帽子组合(总共有 \(2^N\) 种可能性),都必须满足以下两个条件:

  1. 在所有戴白色帽子的人中,至少有一半(向下取整)的人猜对了。
  2. 在所有戴红色帽子的人中,至少有一半(向下取整)的人猜对了。

我们的任务就是设计出这样一套策略,并按照指定的格式输出。

2. 核心思路:从“猜对一半”到“图论模型”

这个问题的关键在于“至少猜对一半(向下取整)”这个条件。比如有 k 个人戴了同色帽子,要求至少有 ⌊k/2⌋ 人猜对。

  • 如果 k 是偶数,比如 k=4,那么要求至少 4/2 = 2 人猜对。这意味着猜对和猜错的人数可以是2对2,3对1,或者4对0。
  • 如果 k 是奇数,比如 k=5,那么要求至少 ⌊5/2⌋ = 2 人猜对。这意味着猜对和猜错的人数可以是2对3,3对2,4对1,或者5对0。

你会发现,这个条件等价于说:猜对的人数猜错的人数最多只相差1。这听起来是不是很像要把一群人“五五开”或者尽量平均地分成两组?

这种“成对”、“一一对应”或者“尽量均分”的性质,很容易让我们联想到图论中的一个经典模型——欧拉路径

在一个图里,如果我们沿着一条欧拉路径(不重复地走完所有边)遍历,那么对于路径中间的任意一个节点,我们“进入”这个节点的次数必然等于“离开”这个节点的次数。这不就是完美的“五五开”吗?

于是,一个大胆的想法诞生了:我们可以把这个问题转化成一个图论问题,通过寻找欧拉路径来给每个人的猜测策略定向,从而满足题目要求。

3. 构建神奇的图

怎么建图呢?图的节点和边应该代表什么?

一个错误的尝试(但有助于理解):
我们可以把 \(2^N\) 种帽子组合(我们称之为“状态”)看作是 \(2^N\) 个节点。如果两个状态只有一个人的帽子颜色不同,我们就在这两个节点间连一条边。比如 (红, 红, 白)(红, 蓝, 白) 只有第二个人颜色不同。这条边就代表了第二个人的“决策点”:当他看到一红一白时,他该猜红还是蓝?我们的任务就是给每条边定一个方向,来代表这个人的猜测。

这个模型很直观,但有个问题:约束条件是按颜色分的(白帽子猜对一半,红帽子猜对一半),而这个模型没法区分这一点。

正解:一个更精妙的图

我们需要一个能体现“颜色”的图。我们可以这样做:

  1. 节点加倍:我们创建 \(2 \times 2^N\) 个节点。对于每一种帽子状态 S(比如 (红, 白, 白)),我们都创建两个对应的节点:

    • 节点W(S):代表状态 S 中,那些戴白色帽子的人。
    • 节点R(S):代表状态 S 中,那些戴红色帽子的人。
    • (在代码实现中,这可以通过给状态编号加上一个大的偏移量来区分,比如 S 对应 节点W(S)S + 2^N 对应 节点R(S))。
  2. 连接边:边代表一个人的一次猜测。一个人的猜测是在什么情况下发生的?当他看到其他 N-1 人的帽子时。

    • 考虑任意一个人 i,和他看到的任意一种 N-1 顶帽子的组合。在这种情况下,他自己的帽子有两种可能:白色或红色。
    • S_wi 戴白帽子的状态,S_ri 戴红帽子的状态。
    • 在状态 S_w 中,i 是个戴白帽子的人,他的决策与 节点W(S_w) 相关。
    • 在状态 S_r 中,i 是个戴红帽子的人,他的决策与 节点R(S_r) 相关。
    • 由于这两种情况是同一个人 i 在同一个观测下面临的决策,我们将 节点W(S_w)节点R(S_r) 用一条无向边连接起来。

这条边就代表了 i 在看到特定景象时,需要在“猜自己是白”和“猜自己是红”之间二选一。

这个图有什么性质?

  • 对于任意一个状态 S,假设有 b 顶白帽,c 顶红帽。
  • 节点W(S) 的度数(连接的边数)正好是 b,因为每个戴白帽子的人都会产生一条连接到这个节点的边。
  • 节点R(S) 的度数正好是 c,同理。

4. 欧拉路径登场,解决问题!

现在我们有了一个巨大的图。接下来,我们要给所有的边定向

  • 如果边 (节点W(S_w), 节点R(S_r)) 的方向是 W -> R,我们就规定这个人猜红色
  • 如果方向是 R -> W,我们就规定这个人猜白色

这样一来:

  • 一次“猜红”的决策,对 S_r 状态来说是猜对了,对 S_w 状态来说是猜错了。从图上看,就是 节点R(S_r) 得到了一条入边节点W(S_w) 得到了一条出边
  • 一次“猜白”的决策,正好相反。节点W(S_w) 得到一条入边节点R(S_r) 得到一条出边

结论:一个节点的“入度”就代表了在这个状态下,对应颜色的人群中猜对的人数!

我们的目标是:

  • 节点W(S) 的入度 \(\ge \lfloor b/2 \rfloor\)
  • 节点R(S) 的入度 \(\ge \lfloor c/2 \rfloor\)

如何实现?利用欧拉路径的性质!
一个图(或其连通分量)如果所有节点度数都是偶数,就存在欧拉回路。在遍历回路时,任何一个节点的“进入次数”和“离开次数”都相等。也就是说 入度 = 出度

  • 对于 节点W(S),它的总度数是 b。如果 b 是偶数,那么 入度 = 出度 = b/2。满足 入度 >= ⌊b/2⌋
  • 如果有些节点度数是奇数呢?我们可以引入一个“虚拟超级节点”,把所有度数为奇数的节点都和这个虚拟节点连一条边。这样,在新的大图中,所有节点的度数都变成偶数了!
  • 当我们在这个新图上跑欧拉回路时,对于一个原来度数为奇数 b 的节点 W(S),它在新图中的度数是 b+1。跑完欧拉回路后,它在新图中的 入度' = 出度' = (b+1)/2。去掉那条连接虚拟节点的边,它在原图中的入度和出度就会是 (b+1)/2(b-1)/2 的某种组合。无论是哪种,其入度都必然 \(\ge (b-1)/2 = \lfloor b/2 \rfloor\)

完美!问题解决了。

5. 算法实现步骤

  1. 建图

    • 遍历 \(0\)\(2^N-1\) 的所有状态 S
    • 遍历 \(0\)\(N-1\) 的所有人 i
    • 如果 i 在状态 S 中戴的是白帽(比如 S 的第 i 位是0),那么找到 i 戴红帽对应的状态 S' (S 的第 i 位变为1)。
    • 在代表 节点W(S)S 和代表 节点R(S')S' + 2^N 之间连一条无向边。
  2. 处理奇度数点

    • 遍历所有 \(2 \times 2^N\) 个节点。
    • 如果一个节点的度数是奇数,就把它和一个新建的虚拟节点(例如 2^(N+1))相连。
  3. 寻找欧拉路径并定向

    • 从任意一个节点开始进行深度优先搜索(DFS)。为了确保每条边只走一次(这是欧拉路径的核心),我们可以用一个 vis 数组标记走过的,或者像题解代码一样,用一个指针 fst[x] 记录节点 x 的边表已经遍历到哪里了。
    • DFS的路径就构成了欧拉路径(或回路)。当我们从节点 u 走向节点 v 时,就相当于把这条边定向为 u -> v
    • 根据边的方向,我们就能确定对应的猜测是“红”还是“白”,并记录下来。
  4. 输出答案

    • 将记录下的所有猜测结果,按照题目要求的格式(第 i 行是第 i 个人的策略字符串)整理并输出。

总结

这道题的解法极具巧思,它将一个看似与图论无关的逻辑推理问题,通过精妙的建模,转化为了一个经典的图论算法问题——寻找欧拉路径。

核心步骤可以概括为:

  • 识别约束:“猜对至少一半” \(\approx\) “入度/出度尽量均分”。
  • 巧妙建模:用“状态-颜色”节点对 (S, W)(S, R) 来分别承载不同颜色人群的约束,用边连接不同状态下的同一次决策。
  • 算法应用:利用欧拉路径/回路算法天然就能满足“入度/出度均分”的性质,来对图进行定向,从而构造出满足条件的全局策略。

通过这套流程,我们就能找到一个在所有 \(2^N\) 种情况下都满足条件的“万能帽子猜测策略”。

posted @ 2025-07-11 19:55  surprise_ying  阅读(12)  评论(0)    收藏  举报