在洛谷上提交时,需要将两个文件合并成一个提交。
不要引入任何头文件,并在文件头加入以下内容:
void Alice(int N, int M, int A[], int B[] );
void InitG(int V, int U );
void MakeG(int pos, int C, int D );
void Bob(int V, int U, int C[], int D[] );
void InitMap(int N, int M );
void MakeMap(int A, int B );
Alice 居住在 JOI 王国。她计划邀请居住在 IOI 共和国的 Bob。在邀请他之前,她打算将 JOI 王国的航线地图发送给他。JOI 王国是一个由 个岛屿组成的岛国,岛屿编号从 到 。JOI 王国内共有 条航线。对于每个 (),第 条航线连接岛屿 和岛屿 ,且为双向航线。任意两条航线不会连接相同的两个岛屿。她必须使用一台由 JOI 王国运营的特殊电报机。她可以通过该电报机发送一个无向图。然而,当她使用它时,顶点编号和边编号会被随机打乱。
具体而言,信息的发送方式如下。设 为 Alice 发送的图(令 为图 的顶点数, 为图 的边数):
- Alice 指定图 的边数 和边数 。然后,她将数字 分别分配给每个顶点,将数字 分别分配给每条边。
- Alice 指定参数 和 。这些参数描述图 的边,即对于每个 (),图 的第 条边连接顶点 和顶点 。
- 图 的顶点编号由 JOI 王国打乱。首先,JOI 王国生成一个序列 ,它是 的一个排列。然后, 被替换为 ,而 被替换为 。
- 接着,图 的边编号由 JOI 王国打乱。首先,JOI 王国生成一个序列 ,它是 的一个排列。然后, 被替换为 ,而 被替换为 。
- 以下数据被发送给 Bob: 和 的值,以及参数 和 的最新值。
请注意,使用这台电报机只能发送一个简单图。此处,“简单图”指不含重边和自环的图。
换句话说,她可以发送一个满足以下条件的图:对于任意 (), 且 成立;同时,对于任意 (), 成立。
Alice 希望使用顶点数最少的图,将 JOI 王国的航线地图发送给 Bob。
任务
为了帮助 Alice 与 Bob 之间的通信,请编写以下两个程序:
- 给定 JOI 王国的岛屿数量 、航线数量 ,以及表示 JOI 王国航线地图的序列 、,第一个程序应输出 Alice 发送的图 的信息。
- 给定 Bob 收到的图 的信息,第二个程序应恢复 JOI 王国的航线地图。
实现细节
你需要提交两个文件。
第一个文件为 Alice.cpp。该文件应输出 Alice 发送的图的信息。它应实现以下函数。程序应包含头文件 Alicelib.h。
通过以下函数,函数 Alice 输出 Alice 发送的图 的信息。
-
void InitG( int V, int U )
该函数指定图 的顶点数和边数。
- 参数 是图 的顶点数。参数 应为介于 到 (含)之间的整数。若调用该函数时参数超出此范围,你的程序将被视为 Wrong Answer [1]。
- 参数 是图 的边数。参数 应为介于 到 (含)之间的整数。若调用该函数时参数超出此范围,你的程序将被视为 Wrong Answer [2]。
-
void MakeG( int pos, int C, int D )
该函数指定图 的边。
- 参数
pos 是由本次调用指定的边的编号。参数 pos 应为介于 到 (含)之间的整数。若调用该函数时参数超出此范围,你的程序将被视为 Wrong Answer [3]。该函数对相同的参数 pos 不应被调用超过一次;若被多次调用,你的程序将被视为 Wrong Answer [4]。
- 参数 和 是图 中边
pos 的两个顶点。 和 应为介于 到 (含)之间的整数,且应满足 。若 或 不满足这些条件,你的程序将被视为 Wrong Answer [5]。此处, 和 是由函数 InitG 指定的整数。
在函数 Alice 中,调用函数 InitG 一次后,函数 MakeG 应被恰好调用 次。若函数 InitG 被调用两次,你的程序将被视为 Wrong Answer [6]。若在调用函数 InitG 之前调用了函数 MakeG,你的程序将被视为 Wrong Answer [7]。若在函数 Alice 结束时未调用函数 InitG,或函数 MakeG 未被调用 次,你的程序将被视为 Wrong Answer [8]。当函数 Alice 结束时,若 Alice 描述的图 不是一个简单图,你的程序将被视为 Wrong Answer [9]。
若对函数 Alice 的调用被视为 Wrong Answer,你的程序将立即终止。
第二个文件为 Bob.cpp。该文件在给定 Bob 收到的图 的信息后,输出 JOI 王国的航线地图。它应实现以下函数。程序应包含头文件 Boblib.h。
通过以下函数,函数 Bob 恢复 JOI 王国的航线地图,并输出航线地图的信息。
-
void InitMap( int N, int M )
该函数指定 JOI 王国的岛屿数量和航线数量。
- 参数 是恢复出的 JOI 王国岛屿数量。 应为一个整数,且必须等于 JOI 王国实际的岛屿数量。若两者不相等,你的程序将被视为 Wrong Answer [10]。
- 参数 是恢复出的 JOI 王国航线数量。 应为一个整数,且必须等于 JOI 王国实际的航线数量。若两者不相等,你的程序将被视为 Wrong Answer [11]。
-
void MakeMap( int A, int B )
该函数指定 JOI 王国的航线数量。
- 参数 和 表示存在一条连接岛屿 与岛屿 的航线。 和 应为介于 到 (含)之间的整数,且应满足 。若 或 不满足这些条件,你的程序将被视为 Wrong Answer [12]。若在 JOI 王国中不存在连接岛屿 与岛屿 的航线,你的程序将被视为 Wrong Answer [13]。由该函数调用所描述的航线应与之前调用所描述的航线不同。当调用
MakeMap( A, B ) 时,若此前已调用过 MakeMap( A, B ) 或 MakeMap( B, A ),你的程序将被视为 Wrong Answer [14]。
此处, 是由 InitMap 指定的整数值。
在函数 Bob 中,调用函数 InitMap 一次后,函数 MakeMap 应被恰好调用 次。若函数 InitMap 被调用两次,你的程序将被视为 Wrong Answer [15]。若在调用函数 InitMap 之前调用了函数 MakeMap,你的程序将被视为 Wrong Answer [16]。若在函数 Bob 结束时未调用函数 InitMap,或函数 MakeMap 未被调用 次,你的程序将被视为 Wrong Answer [17]。此处, 是由 InitMap 指定的整数值。
若对函数 Bob 的调用被视为 Wrong Answer,你的程序将立即终止。
评分流程
评分按以下方式进行。若你的程序被视为 Wrong Answer,它将立即终止。
(1)调用一次函数 Alice,其参数描述 JOI 王国的航线地图信息。
(2)设 为由函数 Alice 指定的图。调用一次函数 Bob,其参数为图 的顶点编号的随机重排和边编号的随机重排。
(3)你的程序被评分。
重要提示
-
你的程序可以为内部使用实现其他函数,或使用全局变量。提交的文件将与评分器一起编译,并生成一个可执行文件。所有全局变量和内部函数应声明为 static,以避免与其他文件冲突。评分时,程序将作为两个独立进程(Alice 进程和 Bob 进程)运行。Alice 进程与 Bob 进程之间不能共享全局变量。
-
你的程序不应使用标准输入和标准输出。你的程序不应通过任何方式与其他文件通信。但,你的程序可以向标准错误输出调试信息。
编译与测试运行
你可以从竞赛网页下载一个归档文件,其中包含用于测试你程序的样例评分器。该归档文件还包含你程序的一个样例源代码文件。
样例评分器由一个源文件组成,即 grader.cpp。若你的程序为 Alice.cpp 和 Bob.cpp,为测试它们,你需要将这些文件(grader.cpp、Alice.cpp、Bob.cpp、Alicelib.h 和 Boblib.h)放入同一目录,并运行以下命令来编译你的程序:
g++ -std=c++14 -O2 -o grader grader.cpp Alice.cpp Bob.cpp
当编译成功后,将生成可执行文件 grader。
请注意,实际评分器与样例评分器不同。样例评分器将以单个进程方式运行,它将从标准输入读取输入数据,并将结果写入标准输出。