#P12867. [JOI Open 2025] 心灵感应 / Telepathy

    ID: 12643 Type: RemoteJudge 2500ms 1024MiB Tried: 0 Accepted: 0 Difficulty: 7 Uploaded By: Tags>2025交互题Special JudgeJOI(日本)通信题

[JOI Open 2025] 心灵感应 / Telepathy

题目背景

译自 JOI Open 2025 T3「Telepathy」/ 「テレパシー」。

这是一道通信题。请使用 C++20\texttt{\textcolor{red}{C++\,20}} 提交。

不要 #include "telepathy.h"\texttt{\#include "telepathy.h"}

题目描述

这是一道通信题

Aitana 和 Bruno 在游玩 Bolivia 的一座国家公园。园内有 NN 个景点,(N1)(N-1) 条道路,每条道路连接两个景点。可以通过道路从任意一个景点到达任意一个景点。

他们在游玩时走散了。此刻开始,他们必须同时抵达某个景点,在那里汇合。然而,身处亚马逊雨林深处,他俩无法互相通信。他们唯一可以依靠的是手头上的地图,地图刻画了公园的结构。他俩在自己的地图上给每个景点标号了 0,1,,N10,1,\ldots,N-1然而,Aitana 和 Bruno 的标号可能不同

为了汇合,Aitana 和 Bruno 现在开始移动。每一轮,他们同时做以下两件事之一:通过一条道路移动到相邻的景点,或者原地不动。

编程实现一个能够让 Aitana 和 Bruno 汇合的策略。本题中,如果在 6d6d 轮内让他俩汇合,可以获得满分;这里,dd 是 Aitana 景点到 Bruno 景点最短路上的边数。注意,如果他们在道路中间相遇,不算作汇合。

本题单个测试点内有 QQ 组测试数据。

形式化题意

我们形式化地描述题意。

国家公园的每个景点都分配了一个 0N10\sim N-1 的标号,第 jj0jN20\le j\le N-2)条道路连接标号为 uj,vju_j,v_j 的景点。标号为 ii0iN10\le i\le N-1)的景点在 Aitana 的地图上标号为 pip_i,在 Bruno 的地图上标号 qiq_i。这里,(p0,p1,,pN1)(p_0,p_1,\ldots,p_{N-1})(q0,q1,,qN1)(q_0,q_1,\ldots,q_{N-1})(0,1,,N1)(0,1,\ldots,N-1) 的排列。

Aitana 知道,对于 j=0,1,,N2j=0,1,\ldots,N-2,有一条连接标号 Aj,BjA_j,B_j 的景点的道路,并且此时她位于标号为 SS 的景点。这里的「标号」指的是 Aitana 地图上的标号。从而,第 j(0jN2)j\, (0\le j\le N-2) 条路连接着标号 puj,pvjp_{u_j},p_{v_j} 的景点,并且令 Aitana 现在所在的景点标号为 ss,有 S=psS=p_s。注意,道路不一定按顺序给出,也不一定是 uj,vju_j,v_j 的顺序。类似地,Bruno 知道,对于 j=0,1,,N2j=0,1,\ldots,N-2,有一条连接标号 Cj,DjC_j,D_j 的景点的道路,并且此时她位于标号为 TT 的景点。这里的「标号」指的是 Bruno 地图上的标号。特别地,令 Bruno 现在所在的景点标号为 tt,有 T=qtT=q_t

根据已知信息,Aitana 和 Bruno 决定他们接下来 10N10N 轮的动向。换言之,Aitana 选定标号序列 x0,x1,,x10Nx_0,x_1,\ldots,x_{10N},Bruno 选定标号序列 y0,y1,,y10Ny_0,y_1,\ldots,y_{10N},表示他们各自的动向。以下条件必须满足:

  • x0=Sx_0=S1k10N\forall 1\le k\le 10N,要么 xk=xk1x_k=x_{k-1},要么(在 Aitana 的地图中)标号 xk,xk1x_k,x_{k-1} 的节点有道路连接。
  • y0=Ty_0=T1k10N\forall 1\le k\le 10N,要么 yk=yk1y_k=y_{k-1},要么(在 Bruno 的地图中)标号 yk,yk1y_k,y_{k-1} 的节点有道路连接。

Aitana 与 Bruno 汇合时的轮数 kk^* 指最小的满足(Aitana 的地图中)标号 xkx_k 的景点与(Bruno 的地图中)标号 yky_k 的景点代表着同一个景点的 kk。获得满分,当且仅当 k6dk^*\le 6d

实现细节

这是一道通信题。你不应该,也不需要定义 main 函数。

不要 #include "telepathy.h"\texttt{\#include "telepathy.h"}

你应该定义以下的函数:

vector<int> Aitana(int N, vector<int> A, vector<int> B, int S, int subtask);

该函数实现了 Aitana 的策略。每组测试数据中该函数被调用恰好一次,所以该函数一共会被调用 QQ 次。

  • N\texttt{N} 指国家公园的景点数 NN
  • A,B\texttt{A},\texttt{B} 均为长度 N2N-2 的数组,0jN2\forall 0\le j\le N-2A[j],B[j]\texttt{A[j]},\texttt{B[j]} 是一条道路连接着的两个景点的标号 Aj,BjA_j,B_j
  • S\texttt{S} 为 Aitana 当前所在景点的标号。
  • subtask\texttt{subtask} 指该测试点所在的子任务编号,只能为 1,2,31,2,3 之一。
  • 返回一个数组 [x0,x1,,x10N][x_0,x_1,\ldots,x_{10N}],描述 Aitana 的动向。
  • 返回的数组长度必须为 10N+110N+1,否则会被判为 Wrong Answer[1]\texttt{Wrong Answer\,[1]}
  • 对于任意 k(0k10N)k\, (0\le k\le 10N),必须有 0xkN10\le x_k\le N-1,否则会被判为 Wrong Answer[2]\texttt{Wrong Answer\,[2]}
  • 必须有 x0=Sx_0=S,否则会被判为 Wrong Answer[3]\texttt{Wrong Answer\,[3]}
  • 对于任意 k(1k10N)k\, (1\le k\le 10N),要么 xk=xk1x_k=x_{k-1},要么标号 xk,xk1x_k,x_{k-1} 的景点有道路连接。否则会被判为 Wrong Answer[4]\texttt{Wrong Answer\,[4]}

以上的「标号」指的是 Aitana 地图上的标号。

vector<int> Bruno(int N, vector<int> C, vector<int> D, int T, int subtask);

该函数实现了 Bruno 的策略。每组测试数据中该函数在调用 Aitana 后被调用恰好一次,所以该函数一共会被调用 QQ 次。

  • N\texttt{N} 指国家公园的景点数 NN
  • C,D\texttt{C},\texttt{D} 均为长度 N2N-2 的数组,0jN2\forall 0\le j\le N-2C[j],D[j]\texttt{C[j]},\texttt{D[j]} 是一条道路连接着的两个景点的标号 Cj,DjC_j,D_j
  • T\texttt{T} 为 Bruno 当前所在景点的标号。
  • subtask\texttt{subtask} 指该测试点所在的子任务编号,只能为 1,2,31,2,3 之一。
  • 返回一个数组 [y0,y1,,y10N][y_0,y_1,\ldots,y_{10N}],描述 Bruno 的动向。
  • 返回的数组长度必须为 10N+110N+1,否则会被判为 Wrong Answer[5]\texttt{Wrong Answer\,[5]}
  • 对于任意 k(0k10N)k\, (0\le k\le 10N),必须有 0ykN10\le y_k\le N-1,否则会被判为 Wrong Answer[6]\texttt{Wrong Answer\,[6]}
  • 必须有 y0=Ty_0=T,否则会被判为 Wrong Answer[7]\texttt{Wrong Answer\,[7]}
  • 对于任意 k(1k10N)k\, (1\le k\le 10N),要么 yk=yk1y_k=y_{k-1},要么标号 yk,yk1y_k,y_{k-1} 的景点有道路连接。否则会被判为 Wrong Answer[8]\texttt{Wrong Answer\,[8]}

以上的「标号」指的是 Bruno 地图上的标号。

如果在 10N10N 轮内 Aitana 和 Bruno 没有汇合,换句话说,0k10N\forall 0\le k\le 10N,(Aitana 的地图中)标号 xkx_k 的景点与(Bruno 的地图中)标号 yky_k 的景点均为不同的景点,你的程序会被判为 Wrong Answer[9]\texttt{Wrong Answer\,[9]}

重要说明

  • 你可以在程序中定义其他函数或使用全局变量。在实际评测时,你的程序将会以两个不同的进程(Aitana,Bruno)运行,这两个进程无法共享全局变量。
  • 你的程序不得使用标准输出输出,禁止以任何方式与任何文件交互。你可以输出调试信息到标准错误流。

编译运行

你可以在「附件」中下载附件压缩包,压缩包中包含 Sample Grader 和本题的示例文件。

Sample Grader 是文件 grader.cpp\texttt{grader.cpp}。为测试程序,将 $\texttt{grader.cpp},\texttt{telepathy.cpp},\texttt{telepathy.h}$ 置于同一目录下,用以下命令来编译:

g++ -std=gnu++20 -O2 -o grader grader.cpp telepathy.cpp

此外,你也可以运行压缩包中的 compile.sh\texttt{compile.sh} 来编译:

./complie.sh

若编译成功,会生成名为 grader\texttt{grader} 的可执行文件。

注意,实际测评时使用的 Grader 与 Sample Grader 不同。Sample Grader 以单进程方式执行,从标准输入流读入数据并将结果输出至标准输出流。

输入格式

Sample Grader 从标准输入流读入以下格式的数据(这里,测试数据编号 0Q10\sim Q-1subtask\mathrm{subtask} 指子任务编号):

subtask\mathrm{subtask}
QQ
(第 00 组数据的内容)
(第 11 组数据的内容)
\vdots
(第 (Q1)(Q-1) 组数据的内容)

每组数据格式如下:

NN
u0u_0 v0v_0
u1u_1 v1v_1
\vdots
un2u_{n-2} vn2v_{n-2}
p0p_0 p1p_1 \ldots pN1p_{N-1}
q0q_0 q1q_1 \ldots qN1q_{N-1}
ss tt

关于各变量的含义,请阅读「形式化题意」部分。注意没有直接输入 Aitana 地图和 Bruno 地图的信息。

将道路打乱的方式由伪随机数决定,伪随机数的结果在各次运行中均相同。如果想要更换随机数种子,将随机数种子作为第一个参数运行 Sample Grader:

./grader 20250615

输出格式

Sample Grader 输出 QQ 行到标准输出流,依次表示每组测试数据的信息:

  • 若该组数据正确,依次输出汇合轮数 kk^{*}dd(Aitana 当前所在景点与 Bruno 当前所在景点的最短路上的边数),例如 Case #0: Accepted 5 2\texttt{Case \#0: Accepted 5 2}
  • 否则,输出错误类型,如 Case #0: Wrong Answer [1]\texttt{Case \#0: Wrong Answer [1]}
2
1 3
0 1
1 2
2 1 0
2 0 1
1 0

提示

注意事项

实际评测时,输入未必在程序执行前就确定了,有可能会根据 AitanaBruno 的返回值确定。

样例解释

返回值中,若干部分被省略了,实际上每个返回值都是长度为 3131 的数组。

调用 AitanaAitana(3,[0,1],[1,2],1,2)\texttt{Aitana(3,[0,1],[1,2],1,2)},返回 [1,0,0,1,2,...,2]\texttt{[1,0,0,1,2,...,2]}

调用 BrunoBruno(3,[1,0],[2,0],2,2)\texttt{Bruno(3,[1,0],[2,0],2,2)},返回 [2,2,0,0,1,...,1]\texttt{[2,2,0,0,1,...,1]}

该样例中,国家公园的结构以及 Aitana、Bruno 地图上的信息如图所示:

Aitana 的动向是:每一轮中,她分别在(她地图中)标号 1,0,0,1,2,,21,0,0,1,2,\ldots,2 的景点。Bruno 的动向是:每一轮中,他分别在(他地图中)标号 2,2,0,0,1,,12,2,0,0,1,\ldots,1 的景点。他们第 33 轮结束时汇合。此时,Aitana 在(她地图中)标号 11 的景点,Bruno 在(他地图中)标号 00 的景点,这两个实际上是同一个景点。

数据范围

本题中,单组数据中至多有 201201 个测试点(即 1Q2011\le Q\le 201)。每个测试点满足以下的限制:

  • 2N2002\le N\le 200
  • (p0,p1,,pN1)(p_0,p_1,\ldots,p_{N-1})(0,1,,N1)(0,1,\ldots,N-1) 的排列;
  • (q0,q1,,qN1)(q_0,q_1,\ldots,q_{N-1})(0,1,,N1)(0,1,\ldots,N-1) 的排列;
  • 0ujN1(0jN2)0\le u_j\le N-1\, (0\le j\le N-2)
  • 0vjN1(0jN2)0\le v_j\le N-1\, (0\le j\le N-2)
  • 从任意景点,可通过道路移动到任意景点;
  • 0sN10\le s\le N-1
  • 0tN10\le t\le N-1
  • sts\neq t

子任务

  • Subtask 1 (40 pts)\text{Subtask 1 (40 pts)}(p0,p1,,pN1)(p_0,p_1,\ldots,p_{N-1})=(q0,q1,,qN1)=(0,1,,N1)(q_0,q_1,\ldots,q_{N-1})=(0,1,\ldots,N-1)
  • Subtask 2 (40 pts)\text{Subtask 2 (40 pts)}uj=j,vj=j+1u_j=j,v_j=j+10jN20\le j\le N-2);
  • Subtask 3 (20 pts)\text{Subtask 3 (20 pts)}:无额外限制。

计分方式

kk^{*} 表示 Aitana 和 Bruno 汇合的轮数,dd 表示 Aitana 当前所在景点与 Bruno 当前所在景点的最短路上的边数。令 α\alpha 表示该子任务重 kd\frac{k^*}{d} 的最大值。

如果该子任务中你的程序被判为错误,得零分。否则,按照以下方式得分(若同时满足多个条件,则取最高的分数):

  • 若任意数据都有 k10Nk^*\le 10N,得 15%15\% 的分。
  • 若任意数据都有 kmax(10d,N)k^*\le \max(10d,N),得 25%25\% 的分。
  • 若任意数据都有 k10dk^*\le 10d
    • 9<α109\lt \alpha\le 10,得 40%40\% 的分;
    • 0<α90\lt \alpha\le 9,得 10020(α6)%\lfloor 100-20(\alpha-6)\rfloor \% 的分;
    • α6\alpha\le 6,得 100%100\% 的分。