P10873 [COTS 2022] 帽子 Šeširi 解题报告
解题报告:P10873 [COTS 2022] 帽子 Šeširi
1. 问题分析:我们要解决什么?
想象一下,你和N-1个朋友站成一圈,每个人头上都戴了一顶帽子,颜色非红即白。你看得见所有其他人的帽子,但唯独看不见自己的。现在,你们需要事先商量好一个“万能策略”。这个策略的规则是:当你看到某种特定的N-1顶帽子的组合时,你应该猜自己戴的是什么颜色的帽子。
这个“万能策略”必须非常厉害,要保证无论老天爷给你们分配了怎样的帽子组合(总共有 \(2^N\) 种可能性),都必须满足以下两个条件:
- 在所有戴白色帽子的人中,至少有一半(向下取整)的人猜对了。
- 在所有戴红色帽子的人中,至少有一半(向下取整)的人猜对了。
我们的任务就是设计出这样一套策略,并按照指定的格式输出。
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\) 个节点。如果两个状态只有一个人的帽子颜色不同,我们就在这两个节点间连一条边。比如 (红, 红, 白)
和 (红, 蓝, 白)
只有第二个人颜色不同。这条边就代表了第二个人的“决策点”:当他看到一红一白时,他该猜红还是蓝?我们的任务就是给每条边定一个方向,来代表这个人的猜测。
这个模型很直观,但有个问题:约束条件是按颜色分的(白帽子猜对一半,红帽子猜对一半),而这个模型没法区分这一点。
正解:一个更精妙的图
我们需要一个能体现“颜色”的图。我们可以这样做:
-
节点加倍:我们创建 \(2 \times 2^N\) 个节点。对于每一种帽子状态
S
(比如(红, 白, 白)
),我们都创建两个对应的节点:节点W(S)
:代表状态S
中,那些戴白色帽子的人。节点R(S)
:代表状态S
中,那些戴红色帽子的人。- (在代码实现中,这可以通过给状态编号加上一个大的偏移量来区分,比如
S
对应节点W(S)
,S + 2^N
对应节点R(S)
)。
-
连接边:边代表一个人的一次猜测。一个人的猜测是在什么情况下发生的?当他看到其他
N-1
人的帽子时。- 考虑任意一个人
i
,和他看到的任意一种N-1
顶帽子的组合。在这种情况下,他自己的帽子有两种可能:白色或红色。 - 令
S_w
是i
戴白帽子的状态,S_r
是i
戴红帽子的状态。 - 在状态
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. 算法实现步骤
-
建图:
- 遍历 \(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
之间连一条无向边。
- 遍历 \(0\) 到 \(2^N-1\) 的所有状态
-
处理奇度数点:
- 遍历所有 \(2 \times 2^N\) 个节点。
- 如果一个节点的度数是奇数,就把它和一个新建的虚拟节点(例如
2^(N+1)
)相连。
-
寻找欧拉路径并定向:
- 从任意一个节点开始进行深度优先搜索(DFS)。为了确保每条边只走一次(这是欧拉路径的核心),我们可以用一个
vis
数组标记走过的边,或者像题解代码一样,用一个指针fst[x]
记录节点x
的边表已经遍历到哪里了。 - DFS的路径就构成了欧拉路径(或回路)。当我们从节点
u
走向节点v
时,就相当于把这条边定向为u -> v
。 - 根据边的方向,我们就能确定对应的猜测是“红”还是“白”,并记录下来。
- 从任意一个节点开始进行深度优先搜索(DFS)。为了确保每条边只走一次(这是欧拉路径的核心),我们可以用一个
-
输出答案:
- 将记录下的所有猜测结果,按照题目要求的格式(第
i
行是第i
个人的策略字符串)整理并输出。
- 将记录下的所有猜测结果,按照题目要求的格式(第
总结
这道题的解法极具巧思,它将一个看似与图论无关的逻辑推理问题,通过精妙的建模,转化为了一个经典的图论算法问题——寻找欧拉路径。
核心步骤可以概括为:
- 识别约束:“猜对至少一半” \(\approx\) “入度/出度尽量均分”。
- 巧妙建模:用“状态-颜色”节点对
(S, W)
和(S, R)
来分别承载不同颜色人群的约束,用边连接不同状态下的同一次决策。 - 算法应用:利用欧拉路径/回路算法天然就能满足“入度/出度均分”的性质,来对图进行定向,从而构造出满足条件的全局策略。
通过这套流程,我们就能找到一个在所有 \(2^N\) 种情况下都满足条件的“万能帽子猜测策略”。