本題為互動題,限用 C++ 作答。你可以在這裡找到範例實作以及範例評分程式,詳細注意事項以及常見問題請參考 Hints。
熟知世界各地的植被,而在地理遊戲「Geoguessr」大賽獲得冠軍的你,最近想要有個新的挑戰。於是你決定玩現在最新的解謎遊戲:Treeguessr!這個遊戲一開始有一個未知的樹 $T$,而玩家的目標就是要知道樹的長相。
每個回合,玩家可以在某些節點放下訊號源,並且在回合結束之前移動到某個地方。當回合結束時,玩家會拿起感測器,並且測得最近的訊號源與玩家自身位置的距離。下一回合開始時,訊號源會全部消失,玩家就會重複上面的操作,直到猜出整棵樹為止。
具體來說,玩家每個回合可以詢問 $\textrm{query}(p, S)$,其中 $p$ 是玩家所在的節點編號,$S$ 是訊號源的節點編號集合,而玩家會得到
$$\textrm{query}(p, S) = \min_{s \in S} \left(\textrm{dis}(p, s)\right)$$
其中 $\textrm{dis}(p, s)$ 是 $p$ 跟 $s$ 的距離。
在這個遊戲中,回合數用的越少,分數就越高。請在最少的回合數內判斷出 $T$,贏得 Treeguessr 的勝利!
詳細細節與評分方式請見後續段落。
你的程式需要在一開始使用前置處理器引入 lib0906.h,詳細請參考範例實作。
你需要完成以下的一個函式:
std::vector<std::pair<int, int>> treeguessr(int n);
treeguessr 會被呼叫恰一次。n 為遊戲中樹的節點數。你可以呼叫以下函式:
int query(int p, std::vector<int> S);
query 不得被呼叫超過 $\textbf{2\ 000\ 000}$ 次。如果任意一個條件沒有被滿足,你的程式會被判斷為 Wrong Answer 並且獲得 0 分,否則,你的程式將依照 Scoring 中的敘述評分。
 
| 評測程式端 | 參賽者程式端 | 
|---|---|
呼叫 treeguessr(4)。 |     |
呼叫 query(1, {4})。 |   |
回傳 2。 |   |
呼叫 query(2, {1, 4})。 |   |
回傳 1。 |   |
呼叫 query(3, {1})。 |   |
回傳 1。 |   |
呼叫 query(4, {1, 2})。 |   |
回傳 2。 |   |
回傳 {{1, 2}, {1, 3}, {3, 4}}。 |   
query 的次數最大值為 $q$,你的得分會是該子題的得分乘上倍數 $p$,由下列方式計算: 
範例評分程式以下列方式輸入:
範例評分程式以下列方式輸出:
如果你的程式被判斷為 Accepted,範例評分程式會輸出 Accepted: q,其中 q 為呼叫 query 的次數。接著輸出 $n - 1$ 行,第 $i$ 行有兩個整數 $u_i, v_i$ 代表你回傳的第 $i$ 條邊連接的點。
如果你的程式被判斷為 Wrong Answer,範例評分程式會輸出 Wrong Answer: MSG,其中 MSG 以及其代表的意思為以下列表的其中一個:
p must be between 1 and n: query 函式傳入的 $p$ 不在 $1$ 至 $n$ 的範圍內。S must be nonempty: query 函式傳入的 $S$ 為空。elements in S must be between 1 and n: query 函式傳入的 $S$ 內有不在 $1$ 至 $n$ 範圍內的數。Too many queries: query 的呼叫次數過多。invalid answer:回傳的陣列長度不是 $n - 1$。如果有多個原因,範例評分程式只會輸出任何一個。
另外請注意,範例評分程式並不會幫你檢查你回傳的數值是否是正確的。
4 1 2 1 3 3 4
由於 Windows Defender 以及各種奇怪東西的限制,本題的範例編譯指令不提供 Windows 批次檔。編譯及測試教學請參考下列說明。
treeguessr.exe,請直接用命令列執行該檔案。-static 參數移除,其餘與 Linux 相同。#include "grader.cpp",並且以單一檔案的編譯執行方式測試,請注意這一行上傳時需要刪除,否則你會獲得一個 Compile Error。| No. | Testdata Range | Constraints | Score | 
|---|---|---|---|
| 1 | 0 | 範例測資 | 0 | 
| 2 | 0~18 | 所有點與節點 $1$ 的距離不超過 $2$ | 25 | 
| 3 | 0~48 | 無額外限制 | 75 |