🔗 CF2179F Blackslex and Another RGB Walking

rating: 1982

Problem Statement

本題為一道 Run-Twice 類型的通信題 (Communication Problem)。

關於通信題 (Communication Problems)

這是一類新的題目類型,程式會被執行 兩次,且遵循以下規則:

  • 獨立執行:兩次執行之間的記憶體與變數狀態不會保留
  • 溝通機制:第一次執行的輸出內容,某種程度上會影響或成為第二次執行的輸入資訊(視題目而定),這是兩階段間唯一的溝通橋樑。
  • 輸入輸出:兩次執行的輸入與輸出格式通常不同。
  • 資源限制:兩次執行的時間與空間限制是分開計算的。例如時限 2 秒,只有當單次執行超過 2 秒才會被判 TLE(如果兩次各用 1.5 秒則是合法的)。
  • 互動性:此類題目也可能同時是互動題 (Interactive),需注意 IO 格式與 Flush 操作。
題目簡述

給定一個二分連通圖,節點數 nn,邊數 mm
第一階段 (Player A):得知完整圖結構,需將每個頂點染成 R, G, B 三色之一。
第二階段 (Player B):被隨機放置在 vv (v1v \neq 1),無法得知自身編號與顏色,僅能看見所有鄰居的顏色。需根據鄰居顏色選擇移動到一個更靠近節點 11 的鄰居。

Constraints

約束條件

  • 2n105,n1m1052 \le n \le 10^5, n-1 \le m \le 10^5
  • 1q1051 \le q \le 10^5
  • d(v)2105\sum d(v) \le 2 \cdot 10^5
  • 圖保證為二分圖且連通。
  • 第二階段的輸入是 非適應性 (Non-adaptive) 的。
非適應性 (Non-adaptive)

這意味著 Player B 面對的詢問(起始位置)是固定的,不會因為 Player A 的染色方式不同而改變。換句話說,Judge 不會刻意針對你的染色結果去構造「最難」的詢問。


思路:BFS 分層染色

策略分析

由於我們需要引導 Player B 往節點 11 移動,最直觀的想法是利用節點 11 為其建立導航資訊
我們可以使用 BFS 計算每個節點 uu 到節點 11 的最短距離 dist(u)dist(u)
由於無法直接傳遞距離數值,我們利用 模運算 將距離映射到三種顏色:

Color(u)={Redif dist(u)0(mod3)Greenif dist(u)1(mod3)Blueif dist(u)2(mod3)Color(u) = \begin{cases} \text{Red} & \text{if } dist(u) \equiv 0 \pmod 3 \\ \text{Green} & \text{if } dist(u) \equiv 1 \pmod 3 \\ \text{Blue} & \text{if } dist(u) \equiv 2 \pmod 3 \end{cases}

為什麼這樣可行?

題目保證圖是 二分圖 (Bipartite Graph)
在二分圖中,從一點出發的 BFS 分層結構非常嚴謹:任意邊 (u,v)(u, v) 連接的兩點,其距離起點 11 的距離差恰為 11。即 dist(u)dist(v)=1|dist(u) - dist(v)| = 1
這意味著,對於位於距離 dd 的節點 vv (目前所在位置),其鄰居的距離只能是 d1d-1 (父節點方向) 或 d+1d+1 (子節點方向)。

根據 d(mod3)d \pmod 3 的染色規則,相鄰節點的顏色必然不同,且循環順序固定:
RGBR\dots \to R \to G \to B \to R \to \dots

  • Color(v)=RColor(v) = R (00),鄰居可能是 BB (22, 父) 或 GG (11, 子)。
  • Color(v)=GColor(v) = G (11),鄰居可能是 RR (00, 父) 或 BB (22, 子)。
  • Color(v)=BColor(v) = B (22),鄰居可能是 GG (11, 父) 或 RR (00, 子)。

Player B 的決策

在第二階段,Player B 看到鄰居顏色集合 SS。由於 v1v \ne 1,必然存在至少一個父節點 (dist=d1dist = d-1),即 SS 中一定包含父節點的顏色。

  1. S=1|S| = 1

    • 由於父節點 (d1d-1) 與子節點 (d+1d+1) 的顏色差為 2(mod3)2 \pmod 3,它們的顏色 絕對不同
    • 因此,若只看到一種顏色,說明所有鄰居都是父節點(或者剛好沒有子節點)。
    • 決策:直接移動到該顏色對應的任意鄰居
  2. S=2|S| = 2

    • 看到 {G,B}\{G, B\}:自己必為 RR (00)。父節點為 BB (22)。\to 往 Blue 走
    • 看到 {R,B}\{R, B\}:自己必為 GG (11)。父節點為 RR (00)。\to 往 Red 走
    • 看到 {R,G}\{R, G\}:自己必為 BB (22)。父節點為 GG (11)。\to 往 Green 走

複雜度分析

  • 時間複雜度:O(N+M)\mathcal{O}(N+M) 用於第一階段 BFS;第二階段每個 Query 為 O(d(v))\mathcal{O}(d(v))
  • 空間複雜度:O(N+M)\mathcal{O}(N+M) 儲存圖與顏色。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from collections import deque

COLORS = "rgb"

def solve(player):
if player == "first":
n, m = map(int, input().split())

g = [[] for _ in range(n)]
for _ in range(m):
u, v = map(lambda x: int(x) - 1, input().split())
g[u].append(v)
g[v].append(u)

color = [''] * n
vis = [False] * n
vis[0] = True
q = deque([(0, 0)]) # (u, d)
while q:
u, d = q.popleft()
color[u] = COLORS[d % 3]
for v in g[u]:
if not vis[v]:
vis[v] = True
q.append((v, d + 1))
print("".join(color))
else:
q = int(input())
for _ in range(q):
d = int(input())
s = input()
assert len(s) == d

colors = sorted(set(s))
if len(colors) == 1:
c = colors[0]
elif len(colors) == 2:
if 'g' in colors and 'b' in colors:
c = 'b'
elif 'r' in colors and 'b' in colors:
c = 'r'
elif 'r' in colors and 'g' in colors:
c = 'g'
print(s.find(c) + 1)

if __name__ == "__main__":
player = input()
t = int(input())
for _ in range(t):
solve(player)

寫在最後

PROMPT

這裡什麼都沒有。