#P9524. [JOIST 2022] 飞机旅行 / Flights

    ID: 15905 远端评测题 4500ms 2048MiB 尝试: 0 已通过: 0 难度: (无) 上传者: 标签>2022交互题Special Judge通信题JOISC/JOIST(日本)

[JOIST 2022] 飞机旅行 / Flights

题目背景

请使用 C++ 20 提交。

不要引入头文件,并在文件头加入以下内容:

void SetID(int, int);

题目描述

在 JOI 共和国中,有 NN 个机场,编号从 00N1N - 1。有 N1N - 1 条航线,编号从 00N2N - 2。航线 ii0iN20 \le i \le N - 2)双向连接机场 UiU_i 与机场 ViV_i。通过若干条航线相连,可以从任意一个机场到达任意另一个机场。对每个机场,连接它与其他机场的航线数量至多为 33

Benjamin 计划在 JOI 共和国旅行。在旅程的最后一天,他想到达温泉所在的机场。游乐园位于机场 xx,温泉位于机场 yy。由于 Benjamin 对航线一无所知,他将与航空公司的工作人员 Ali 沟通。Benjamin 想知道:从游乐园所在的机场出发,到达温泉所在的机场,最少需要乘坐多少条航线。Ali 掌握航线信息,但 Benjamin 并不知道自己应当乘坐哪些航线。

  1. Ali 为每个机场设置一个 ID 码。ID 码是介于 002N+192N + 19(含)之间的整数。
  2. Benjamin 得到游乐园所在机场的 ID 码 XX,以及温泉所在机场的 ID 码 YY
  3. Benjamin 向 Ali 发送一封电子邮件。该邮件是一串长度 恰好 等于 2020 的字符串,字符串的每个字符均为 0011
  4. Ali 给 Benjamin 回一封信。该信是一串长度在 11300000300\,000(含)之间的字符串,字符串的每个字符均为 0011

请编写程序,实现航空公司工作人员 Ali 与旅客 Benjamin 的策略。注意:在第 22 步中,Benjamin 能得到游乐园与温泉所在机场的 ID 码 X,YX, Y然而 Benjamin 不能获得机场编号 x,yx, y

实现细节

你需要提交两个文件。

Ali.cpp

该文件应实现 Ali 的策略,并实现下述两个函数。程序应使用预处理指令 #include 引入 Ali.h

  • void Init(int N, std::vector<int> U, std::vector<int> V)
    该函数用于为每个机场设置 ID 码(见「评分」中的场景说明),每个场景调用 恰好一次
    • 参数 NN 为 JOI 共和国中的机场数量。
    • 参数 U,VU, V 为长度为 N1N - 1 的数组,即 U[i],V[i]U[i], V[i] 分别是航线 ii0iN20 \le i \le N - 2)连接的机场 Ui,ViU_i, V_i
  • std::string SendA(std::string S)
    该函数实现 Ali 给 Benjamin 的回信策略(见「评分」中的场景说明),在调用 SendB(见下文)之后、每个场景调用 恰好一次
    • 参数 SS 是长度为 2020 的字符串,即 Benjamin 发给 Ali 的电子邮件。
    • 函数 SendA 应返回一个字符串,即 Ali 给 Benjamin 的回信。
    • 返回值的长度必须在 11300000300\,000(含)之间。若不满足,则判为 Wrong Answer [5]
    • 返回值的每个字符必须为 0011。若不满足,则判为 Wrong Answer [6]

对每次调用 Init,下述函数必须对每个机场调用一次,总计调用 NN 次:

  • void SetID(int p, int value)
    • 参数 pp 表示为机场 pp 设置 ID 码。必须满足 0pN10 \le p \le N - 1。若不满足,则判为 Wrong Answer [1]
    • 参数 value 是 Ali 指定的该机场的 ID 码。必须满足 0value2N+190 \le value \le 2N + 19。若不满足,则判为 Wrong Answer [2]
    • 不允许对同一个 pp 调用多次 SetID。若不满足,则判为 Wrong Answer [3]
    • Init 结束时,SetID 的调用次数应为 NN。若不满足,则判为 Wrong Answer [4]

一旦某次 SetID 调用被判为 Wrong Answer,程序将立即终止。

Benjamin.cpp

该文件应实现 Benjamin 的策略,并实现下述两个函数。程序应使用预处理指令 #include 引入 Benjamin.h

  • std::string SendB(int N, int X, int Y)
    该函数实现 Benjamin 发给 Ali 的电子邮件策略(见「评分」中的场景说明),在 Init 调用之后、每个场景调用 恰好一次
    • 参数 NN 为 JOI 共和国中的机场数量。
    • 参数 XX 为游乐园所在机场的 ID 码。
    • 参数 YY 为温泉所在机场的 ID 码。
    • 函数 SendB 应返回 Benjamin 发给 Ali 的邮件字符串。
    • 若返回值不是长度为 2020 的字符串,则判为 Wrong Answer [7]
    • 若返回值的任一字符不是 0011,则判为 Wrong Answer [8]
  • int Answer(std::string T)
    该函数应计算从机场 xx 到机场 yy 的最少乘坐航线数(见「评分」中的场景说明),在 SendA 调用之后、每个场景调用 恰好一次
    • 参数 TT 为 Ali 发给 Benjamin 的回信字符串,长度在 11300000300\,000(含)之间。
    • 函数应返回从机场 xx 到机场 yy 所需的最少航线数量。

重要注意事项

  • 程序可以实现其他内部使用的函数,或使用全局变量。提交的文件将与评测器一同编译,组成单个可执行文件。为避免与其他文件冲突,所有全局变量与内部函数都应声明在匿名命名空间中。评测时将分别作为 Ali 与 Benjamin 两个进程执行。Ali 进程与 Benjamin 进程 不能共享 全局变量。
  • 程序 不得 使用标准输入与标准输出。程序 不得 通过任何方式与其他文件通信。但你可以向标准错误输出调试信息。

评分

一个测试用例由 QQ 个场景组成,编号为 00Q1Q - 1。每个场景给定如下数据(取值范围见「约束」):

  • JOI 共和国的机场数量 NN
  • 游乐园所在的机场编号 xx
  • 温泉所在的机场编号 yy
  • 航线信息 $(U_0, V_0), (U_1, V_1), \dots, (U_{N - 2}, V_{N - 2})$。

对每个场景,依次调用 InitSendBSendAAnswer。你的程序应在这些调用中使用合法参数并返回合法值。调用顺序如下:

  1. k=0,1,,Q1k = 0, 1, \dots, Q - 1,依次执行步骤 2255
  2. 调用 Init,参数按场景 kk 的「实现细节」说明设置。
  3. 调用 SendB,参数按场景 kk 的「实现细节」说明设置。
  4. 调用 SendA,参数按场景 kk 的「实现细节」说明设置。
  5. 调用 Answer,参数按场景 kk 的「实现细节」说明设置。

若程序在这些过程中任一处被判为 Wrong Answer,程序将立即终止,并视为未通过该测试用例。

编译与本地测试

你可以从竞赛网页下载包含样例评测器的压缩包,用于本地测试。压缩包中也包含你程序的样例源文件。

样例评测器文件名为 grader.cpp。为测试你的程序,请将 grader.cppAli.cppBenjamin.cppAli.hBenjamin.h 放在同一目录下,并运行以下命令进行编译:

g++ -std=gnu++17 -O2 -o grader grader.cpp Ali.cpp Benjamin.cpp

若编译成功,将生成可执行文件 grader

注意:实际评测器与样例评测器不同。样例评测器作为单进程执行,从标准输入读取数据并向标准输出写出结果。

输入格式

样例评测器从标准输入读取如下数据。所有输入值均为整数。

QQ
(场景 00 的输入)
(场景 11 的输入)
\vdots
(场景 Q1Q - 1 的输入)

每个场景的输入格式如下:

NN xx yy
U0U_0 V0V_0
U1U_1 V1V_1
\vdots
UN2U_{N - 2} VN2V_{N - 2}

输出格式

如果程序被判为 Wrong Answer [1]–[8] 中的任意一种,样例评测器会输出其类型(引号仅为说明):“Wrong Answer [1]”。

否则,对每个场景,它会输出函数 Answer 的返回值以及 Ali 发给 Benjamin 的字符串的最大长度。样例评测器 不会 检查 Answer 的返回值是否正确。

Scenario 0: Your Answer = 3
Scenario 1: Your Answer = 1
Scenario 2: Your Answer = 4
Scenario 3: Your Answer = 1
Scenario 4: Your Answer = 5
Accepted: Maximum Length = 24

如果你的程序同时满足多种 Wrong Answer 的判定条件,样例评测器只报告其中一种。此外,即使你的程序在后续场景被判为 Wrong Answer [1]–[8],只要在第一个场景未被判错,样例评测器也可能先输出如下中间结果:

Scenario 0: Your Answer = 3
Scenario 1: Your Answer = 1
Scenario 2: Your Answer = 4
Wrong Answer [8]

提示

约束

  • 1Q501 \le Q \le 50
  • 2N100002 \le N \le 10\,000
  • 0Ui<ViN10 \le U_i < V_i \le N - 10iN20 \le i \le N - 2)。
  • 0xN10 \le x \le N - 1
  • 0yN10 \le y \le N - 1
  • xyx \ne y
  • 通过若干条航线相连,可以从任意一个机场到达任意另一个机场。
  • 对每个机场,连接它与其他机场的航线数量至多为 33

子任务

1.(1515 分)Q=1Q = 1
2.(8585 分)Q2Q \ge 2

子任务 1 的评分

若你的程序在子任务 11 的任意场景中被判为 Wrong Answer,则该子任务得分为 00

若你的程序正确回答子任务 11 的所有测试用例,得分按下述规则计算。设 L1L_1 为 Ali 发给 Benjamin 的字符串的最大长度。

L1L_1 的取值 得分
150001L1300000150\,001 \le L_1 \le 300\,000 77
20001L115000020\,001 \le L_1 \le 150\,000 1111
L120000L_1 \le 20\,000 1515

子任务 2 的评分

若你的程序在子任务 22 的任意场景中被判为 Wrong Answer,则该子任务得分为 00

若你的程序正确回答子任务 22 的所有测试用例,得分按下述规则计算。设 L2L_2 为 Ali 发给 Benjamin 的字符串的最大长度。注意:若 1401L21\,401 \le L_2,该子任务得分为 00

L2L_2 的取值 得分
1401L23000001\,401 \le L_2 \le 300\,000 00
71L2140071 \le L_2 \le 1\,400 $52 - 35 \times \log_{10}\!\bigl(\frac{L_2}{70}\bigr)$ 分(向下取整)
45L27045 \le L_2 \le 70 870.5×L287 - 0.5 \times L_2 分(向下取整)
25L24425 \le L_2 \le 44 109L2109 - L_2
L224L_2 \le 24 8585

样例交互

以下为样例评测器的样例输入与对应的函数调用。在该示例中,Ali 在 Init 中为机场 0,1,2,30, 1, 2, 3 设置的 ID 码分别为 12,21,25,2712, 21, 25, 27

样例输入 1

Ali 的调用 Ali 的返回值 Benjamin 的调用 Benjamin 的返回值
Init(4,[0,1,2],[1,2,3])\texttt{Init(4,[0,1,2],[1,2,3])}
SetID(0,12)\texttt{SetID(0,12)}
SetID(1,21)\texttt{SetID(1,21)}
SetID(2,25)\texttt{SetID(2,25)}
SetID(3,27)\texttt{SetID(3,27)}
SendB(12,25)\texttt{SendB(12,25)} "0000011111000011111"\texttt{"0000011111000011111"}
SendA("00...11")\texttt{SendA("00...11")} "10"\texttt{"10"}
Answer("10")\texttt{Answer("10")} 2\texttt{2}

在该样例中,有 N(=4)N (= 4) 个机场与三条航线:

  • 一条连接机场 00 与机场 11 的航线;
  • 一条连接机场 11 与机场 22 的航线;
  • 一条连接机场 22 与机场 33 的航线。

从机场 x(=0)x (= 0) 到机场 y(=2)y (= 2) 至少需要乘坐 22 条航线,因此 Answer 应返回 22

注意:SendB 的返回值并不是机场编号 (x,y)=(0,2)(x, y) = (0, 2),而是机场的 ID 码 (X,Y)=(12,25)(X, Y) = (12, 25)

样例输入 2

2
10 0 9
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
15 12 8
0 1
0 2
1 3
1 4
2 5
2 6
3 7
3 8
4 9
4 10
5 11
5 12
6 13
6 14

在该样例中,Q=2Q = 2 个场景:

  • 对于第一个场景,Answer 应返回 99
  • 对于第二个场景,Answer 应返回 66