#P13782. [eJOI 2022] Where Is the Root?

    ID: 13773 远端评测题 1000ms 2048MiB 尝试: 0 已通过: 0 难度: 7 上传者: 标签>2022交互题Special JudgeeJOI(欧洲)

[eJOI 2022] Where Is the Root?

Description

给定一棵包含 nn 个顶点的树。树是一种图,保证任意两个顶点之间恰好存在一条简单路径。同时保证至少有一个顶点与不少于 3 个顶点直接相连。 其中有一个顶点是根节点,你的任务是找出它。为此,你可以进行如下形式的询问:

  • 给定一个顶点集合 a1,a2,,ama_1, a_2, \ldots, a_m,检查它们的最近公共祖先是否在这个集合中。

对于顶点集合 SS,若顶点 vv 位于从 SS 中所有顶点到根的路径上,则称 vvSS 的公共祖先。集合 SS 的最近公共祖先(LCA)是指离根最远的那个公共祖先。

交互说明

交互开始时,首先读入一个整数 nn4n5004 \leq n \leq 500),表示顶点数量。

接着读入 n1n - 1 行,每行包含两个整数 ai,bia_i, b_i1ai,bin1 \leq a_i, b_i \leq n),表示在顶点 aia_ibib_i 之间有一条边。

保证输入的 n1n - 1 条边构成一棵树,并且至少有一个顶点的度数不小于 3。

你可以通过如下方式发起询问:先输出 "?",再输出一个整数 mm,然后输出 mm 个互不相同的整数 a1,a2,,ama_1, a_2, \ldots, a_m1mn, 1ain1 \leq m \leq n,\ 1 \leq a_i \leq n),表示你想要检查的顶点集合。

交互器会返回 "YES",如果它们的 LCA 属于集合 {a1,a2,,am}\{a_1, a_2, \ldots, a_m\};否则返回 "NO"

你最多可以询问 1000 次,但分数将取决于你的询问次数。输出最终答案不计入询问次数。请参考评分部分获取详细说明。

当你确认根节点后,输出符号 "!",然后输出一个整数 vv1vn1 \leq v \leq n),表示根节点。然后终止程序。

在输出每次询问后,不要忘记输出换行并刷新缓冲区。可以使用:

  • 在 C++ 中使用 fflush(stdout)cout.flush()
  • 在 Python 中使用 stdout.flush()

保证对于每个测试用例,树和其根节点在交互开始前已经固定,交互器不会自适应改变。

7
4 1
1 2
4 3
3 5
3 6
4 7

NO

YES

NO

YES







? 2 5 6

? 3 6 3 5

? 2 1 7

? 2 4 6

! 4

Hint

样例说明

第一次询问:顶点 5566 的 LCA 是顶点 33,不在集合 {5,6}\{5, 6\} 中,因此返回 "NO"

第二次询问:顶点 3,5,63, 5, 6 的 LCA 是顶点 33,在集合中,因此返回 "YES"

第三次询问:顶点 1177 的 LCA 是顶点 44,不在集合中,因此返回 "NO"

第四次询问:顶点 4466 的 LCA 是顶点 44,在集合中,因此返回 "YES"

由此可以推测根节点是顶点 44,这就是正确答案。

评分规则

  1. (7 分):n9n \leq 9
  2. (10 分):n30n \leq 30
  3. (最高 83 分):n500n \leq 500

在前两个子任务中,你最多可以询问 1000 次。

在第三个子任务中,设 kk 为你在某个测试用例中使用的最大询问次数:

  • 如果 k9k \leq 9,你将得到 83 分。
  • 否则,你将得到:$$\left\lfloor \max \left(10,\ 83 \cdot \left(1 - \frac{\ln(k - 6)}{7}\right)\right) \right\rfloor$$

以下是 C++ 代码实现的计分函数:

((k <= 9) ? 83 : max(10, int(83 * (1 - log(k - 6.0) / 7))))

翻译由 ChatGPT-5 完成