loj#P3835. 「IOI2022」千岛
「IOI2022」千岛
注意事项
在 LibreOJ 上,由于语言限制,目前只支持以下语言的提交:
- C++(标准为 C++ 17 及以上)
请在提交源代码前添加 #include "islands.h"
。
题目描述
千岛是爪哇海里一组美丽的岛屿,其中有 个岛屿,编号为从 到 。
有 艘独木舟在岛屿之间航行,编号为从 到 。对于满足 的所有 ,独木舟 可以停靠在岛屿 或 ,并且在岛屿 和 之间航行。具体来说,当独木舟停靠在岛屿 时,可以用它从岛屿 去往岛屿 ,此后该独木舟就变成停靠在岛屿 。类似地,当该独木舟停靠在岛屿 时,它可以从岛屿 航向岛屿 ,此后该独木舟就变成停靠在岛屿 。在初始时,该独木舟停靠在岛屿 。可能有多艘独木舟能用于在同一对岛屿之间航行。也可能会有多艘独木舟停靠在同一个岛屿处。
出于安全考虑,各艘独木舟在每次航行后必须进行维修,因此同一独木舟不允许紧接着完成两次航行。也就是说,在用完某艘独木舟 后,必须先用过另外某艘独木舟,才能再启用独木舟 。
Bu Dengklek 想策划一次在部分岛屿之间的旅行。她的旅程是合理的,当且仅当满足如下条件:
- 她的旅程应从岛屿 开始,并且在该岛屿结束。
- 她应该游览岛屿 之外的至少一个岛屿。
- 在旅行结束后,每艘独木舟应停靠在旅行开始前它所在的岛屿。也就是说,对于满足 的所有 ,独木舟必须停靠在岛屿 。
请你帮助 Bu Dengklek 找出包括至多航行 次的合理旅行,或者告诉她不存在合理旅行。 可以证明,在本题所给出的约束条件下(参见约束条件部分),如果存在合理旅行,则必然存在航行次数不超过 次的合理旅行。
实现细节
你要实现如下函数:
union(bool, int[]) find_journey(int N, int M, int[] U, int[] V)
- :岛屿数量。
- :独木舟数量。
- , :长度为 的两个数组,给出独木舟航行的岛屿。
- 该函数应当返回一个布尔类型或者整数数组。
- 如果不存在合理旅程,该函数应返回
false
。 - 如果存在合理旅程,你有两个选择:
- 如果想得到全部的分数,该函数应返回一个至多包含 个整数的数组,该数组用来刻画一个合理旅程。更确切地说,该数组中的元素应为旅程中所用独木舟的编号(按照独木舟的使用顺序)。
- 如果想得到部分分数,该函数应返回
true
,或返回一个包含超过 个整数的数组,或返回了一个未给出合理旅程的整数数组(更多细节参见“子任务”部分)。
- 如果不存在合理旅程,该函数应返回
- 该函数将被调用恰好一次。
样例 1
考虑如下调用:
find_journey(4, 5, [0, 1, 2, 0, 3], [1, 2, 3, 3, 1])
下图给出了岛屿和独木舟。
一个可行的合理旅行如下。Bu Dengklek 先依次使用独木舟 ,, 和 。结果是她将在岛屿 上。其后,Bu Dengklek 可以再次使用独木舟 ,因为该独木舟正停靠在岛屿 ,而且她用的上一艘独木舟不是 。再次使用独木舟 后,现在 Bu Dengklek 在岛屿 上。然而,独木舟 , 和 没有停靠在旅程开始前它们所在的岛屿。接下来 Bu Dengklek 继续她的旅程,使用独木舟 ,,, 和再一次使用 。Bu Dengklek 回到了岛屿 上,并且所有独木舟都停靠在旅行开始前它们所在的岛屿。
因此,返回结果 刻画了一个合理旅程。
样例 2
考虑如下调用:
find_journey(2, 3, [0, 1, 1], [1, 0, 0])
下图给出了岛屿和独木舟。
Bu Dengklek 仅能从使用独木舟 开始,此后她可以使用独木舟 或者 。注意,她不能连续使用独木舟 两次。在两种情况下,Bu Dengklek 都回到了岛屿 上。然而,有独木舟没停靠在旅行开始前它们所在的岛屿,而 Bu Dengklek 此后却无法再使用任何独木舟,因为唯一停靠在岛屿 的独木舟是她刚用过的那艘。由于不存在合理旅程,该函数应当返回 false
。
约束条件
- ;
- ;
- 且 (对于所有满足 的 );
- (对于所有满足 的 )。
子任务
- (5 分)。
- (5 分) 。 对于每一对不同的岛屿 和 (),恰好有两艘可在它们之间航行的独木舟。 其中一艘停靠在岛屿 ,而另一艘停靠在岛屿 。
- (21 分) , 是偶数,而且对于满足 的所有偶数 ,独木舟 和 都可以用于在岛屿 和 之间航行。独木舟 最初停靠在岛屿 处,而独木舟 最初停靠在岛屿 处。形式化地, 且 。
- (24 分) , 是偶数,而且对于满足 的所有偶数 ,独木舟 和 都可以用于在岛屿 和 之间航行。两艘独木舟最初都停靠在岛屿 处。 形式化地, 且 。
- (45 分)没有额外的约束条件。
对于每个存在合理旅程的测试用例,你的解答:
- 如果返回一个合理旅程,将得到全部分数,
- 如果返回
true
,或返回一个超过 个整数的数组,或返回一个未给出合理旅程的数组,将得到 的分数, - 在其他情况下得分为 。
对于每个不存在合理旅程的测试用例,你的解答:
- 如果返回
false
,将得到全部分数, - 在其他情况下得分为 。
注意,每个子任务上的最终得分,为该子任务中所有测试用例上的最低得分。
评测程序示例
评测程序示例读取如下格式的输入:
- 第 行:;
- 第 行():。
测试程序示例将按照如下格式打印你的答案:
- 如果
find_journey
返回一个bool
:- 第 行:;
- 第 行:如果
find_journey
返回false
则为 ,否则为 。
- 如果
find_journey
返回一个int[]
,该数组中的元素记为 。测试程序示例打印出:- 第 行:;
- 第 行:;
- 第 行:。
约定
题面在给出函数接口时,会使用一般性的类型名称 void
、bool
、int
、int[]
(数组)和 union(bool, int[])
。
在 C++ 中,评测程序会采用适当的数据类型或实现,如下表所示:
void |
bool |
int |
int[] |
---|---|---|---|
void |
bool |
int |
std::vector<int> |
union(bool, int[]) |
数组 a 的长度 |
---|---|
std::variant<bool, std::vector<int>> |
a.size() |
C++ 语言里,std::variant
定义在 <variant>
头文件中。
一个返回类型为 std::variant<bool, std::vector<int>>
的函数可以返回一个 bool
或一个 std::vector<int>
。
以下示例代码给出了三个返回 std::variant
的函数,它们都能正常工作:
std::variant<bool, std::vector<int>> foo(int N) {
return N % 2 == 0;
}
std::variant<bool, std::vector<int>> goo(int N) {
return std::vector<int>(N, 0);
}
std::variant<bool, std::vector<int>> hoo(int N) {
if (N % 2 == 0) {
return false;
}
return std::vector<int>(N, 0);
}