這是一個多輪互動問題。請記得在每次輸出後刷新輸出緩衝區。若要刷新輸出,你可以使用:
- C/C++ 中的
fflush(stdout)或cout.flush(); - Java 和 Kotlin 中的
System.out.flush(); - Python 中的
sys.stdout.flush()。
在經典的線上匹配遊戲中,圖的邊會被逐一揭露。每當一條邊出現時,你必須立即且不可撤銷地決定是否將其納入你的匹配中。你的目標是確保沒有兩條被選中的邊共用同一個頂點,同時最大化所選邊的總數。
你是一位渴望成名的雄心勃勃的計算機科學家。正如你所知,在線上環境中找到最大匹配在機率上幾乎是不可能的——即使對於像二分圖這樣最簡單的圖類也是如此。然而,在別人看到根本障礙的地方,你看到了榮耀的機會。今天,你聲稱已經破解了樹結構長期以來的開放性問題,並準備向世界展示你的突破性演算法。
只有一個問題:昨天,你在證明中發現了一個錯誤,而你仍然不知道如何修復它。不願放棄聚光燈的你,決定將你的演示變成一場魔術表演——你的助手隱藏在後台,將在遊戲開始前傳輸關於整個 $n$ 個頂點樹的一點提示。
你最初的計劃很簡單:讓你的助手直接發送每個邊查詢的答案。為此,你安裝了一個秘密耳機,能夠接收長度為 $(n - 1)$ 的單一二進位字串。但觀眾對你的「突破」持懷疑態度。為了防止任何預先安排的詭計,他們要求邊以均勻隨機的順序呈現——這種順序既不是你也不是你的助手可以預測或控制的。
舞台已經搭好。燈光聚焦在你身上。現在證明你的主張——不要換台。
互動
你的程式在每個測試中會被執行兩次。在 prepare 回合中,你的程式將扮演助手的角色。在 play 回合中,你的程式將扮演魔術師(你)的角色。在任一回合中,你的程式都將作為互動程序進行評估。
Prepare 回合
輸入的第一行包含單字 prepare。第二行包含一個整數 $n$ ($2 \le n \le 500$),代表頂點數量。接下來的 $(n - 1)$ 行,每行包含兩個整數 $u$ 和 $v$ ($1 \le u, v \le n, u < v$),表示樹中 $u$ 和 $v$ 之間的一條無向邊。
你必須輸出一行,包含一個長度恰好為 $(n - 1)$ 的二進位字串 $s$,僅由字元 0 和 1 組成。這是傳輸給第二個 play 回合的字串。如果你的輸出不符合所需格式,你將收到 Wrong Answer 的判決。
Play 回合
你的程式將為 play 回合重新啟動。
第一行包含單字 play。第二行包含整數 $n$。第三行包含你在 prepare 回合中輸出的二進位字串 $s$。
之後,遊戲開始,共有 $(n - 1)$ 個回合。在每一回合中,會提供一行包含兩個整數 $u$ 和 $v$ ($1 \le u, v \le n, u < v$)。作為回應,你應該輸出一行,包含 take 或 ignore。第一回合中的所有邊將會被提供恰好一次,且邊的順序是從 $(n - 1)!$ 種可能的排列中均勻隨機選擇的。
當輸出格式無效時,遊戲將立即結束,互動器不會提供進一步資訊。
評分標準
令 $M$ 為你的程式所選取的邊集。如果沒有頂點與超過一條選取的邊相關聯,且 $|M| = |M^*|$(其中 $M^*$ 是該圖的最大匹配),則視為可接受。
除了範例測試外,共有 50 個測試。為了通過本題,你的程式必須在所有測試(包括範例測試)上均正確。
所有洗牌順序保證在接收程式輸出前已固定。隨機性對於每個測試都是固定的,透過固定偽隨機數產生器的種子來實現。
提供了一個測試工具來幫助你開發和測試你的程式。
範例
輸入 1 (Pass 1)
prepare 3 1 2 1 3
輸出 1 (Pass 1)
00
輸入 1 (Pass 2)
play 3 00 1 3
輸出 1 (Pass 2)
take
輸入 2 (Pass 2)
1 2
輸出 2 (Pass 2)
ignore
說明
範例 1 的說明:由於 $|M^*| = 1$,選取任何一條邊都是可接受的,且提示可以是任意的。
Figure 1. Magically Marked Matching Master