在本题中,你将扮演信息学奥林匹克竞赛的评测人员。你正在为其中一道题目准备测试数据。你发现了一个有缺陷的解法,现在需要准备一些测试,使得该解法无法通过。本题由三个子任务组成。你的任务是编写一个程序,根据输入数据判断当前对应的是哪个子任务,并为该子任务生成合适的解答。
由于你的程序将用于生成测试数据,因此它必须严格按照给定规格输出数据。需要特别注意空格和换行符的输出格式。尤其是,在输出的最后,必须恰好输出一个换行符。
题目文件
- quicksort.cpp
- dijkstra_wolna.cpp
- dijkstra_poprawna.cpp
- bfs_poprawny.cpp
以上文件中包含了后续将要提到的源代码。
注意:本题总分为 150 分。
子任务 1.(50 分)
本子任务中,给定一个包含 $n$ 个整数的序列,需要将其排序。在文件 quicksort.cpp 中给出了一个实现了快速排序(Quicksort)算法的解法。由于其选择划分元素的方法,这个解法在某些情况下可能运行得很慢。你的任务是编写一个程序,生成这样的测试数据,使得在 quicksort 函数中两个内部 while 循环的总迭代次数至少为 $50n$。
输入格式
输入仅有一行,包含单词 sortowanie,随后是一个整数 $n$($200 \leq n \leq 100{,}000$)。
输出格式
你的程序应当按照如下格式输出作为 quicksort.cpp 程序的输入数据。输出的第一行应为从输入中读入的整数 $n$。第二行应包含 $n$ 个整数 $a_i$($1 \leq a_i \leq 10^9$)。
子任务 2.(50 分)
本子任务中,给定一个大小为 $n \times n$ 的正方形棋盘,由 $n^2$ 个方格组成。棋盘上有一个棋子。每一步中,棋子可以移动到当前所在格子的四个相邻格子之一。棋盘上的一些格子是禁止的,棋子不能进入这些格子。其余格子称为可用格子。目标是计算,对于每一个可用格子,棋子最少需要多少步才能到达该格子。该问题的正确解法位于文件 bfs_poprawny.cpp 中,使用了基于 STL 中 queue 模板的 BFS 算法实现。
然而,很容易犯一个(并不明显的)错误:使用了一种假设队列中任意时刻最多只会有 1000 个元素的队列实现。在本子任务中,你的程序应当输出一个测试,使得上述过程在执行的某一时刻,队列中存储的元素数量超过 1000 个。
输入格式
输入仅有一行,包含单词 bfs,随后是一个整数 $n$($300 \leq n \leq 2000$)。
输出格式
你的程序应当按照如下格式输出作为 bfs_poprawny.cpp 程序的输入数据。第一行应包含从输入中读入的整数 $n$,以及两个整数 $p_x$ 和 $p_y$($1 \leq p_x, p_y \leq n$),表示棋子起始于第 $p_x$ 行、第 $p_y$ 列。
接下来应给出棋盘的描述,共 $n$ 行,每行包含 $n$ 个字符 # 和/或 .,分别表示禁止格子和可用格子。起始格子必须是可用格子。
对于给定的棋盘,在 bfs_poprawny.cpp 程序中,加入队列的元素数量应当超过 1000 个。
子任务 3.(50 分)
本子任务要求编写一个算法,用于在一个无向图中寻找最短路径,图中边的长度为正整数。图由 $n$ 个顶点组成,编号为 $1,\ldots,n$。目标是计算从顶点 1 到图中每一个顶点的最短距离。正确的解法位于文件 dijkstra_poprawna.cpp 中,其实现了(略作修改的)Dijkstra 算法,并使用了 STL 中的 priority_queue(优先队列)。
修改的简要说明
在标准的 Dijkstra 算法中,对于每一个尚未访问的顶点,如果已经找到了一条到达它的路径,就会在优先队列中保存该路径的长度,并在路径被更新时修改该值。附带代码中的修改在于:当发现了一条到达某个顶点的更短路径时,直接将一个新的元素加入优先队列。原先表示旧距离的队列元素从此成为队列中的“垃圾”,因此在从队列中取出元素时,需要检查是否遇到了这样的“垃圾”,并在必要时跳过其处理(参见代码中的 break 指令)。
这里可能犯的一个错误,是用普通队列来代替优先队列。这样的实现位于文件 dijkstra_wolna.cpp 中。虽然它是正确的,但在某些情况下运行速度会慢得多。
你的任务是编写一个程序,生成这样的测试数据,使得第二个程序中内部的 for 循环执行次数至少是第一个程序中对应循环的 20 倍。
输入格式
输入仅有一行,包含单词 sciezki,随后是一个整数 $n$($300 \leq n \leq 100{,}000$)。
输出格式
你的程序应当按照如下格式输出作为 dijkstra_poprawna.cpp 和 dijkstra_wolna.cpp 程序的输入数据。输出的第一行应包含从输入中读入的整数 $n$,以及一个整数 $m$($1 \leq m \leq 5n$)。其中,$n$ 表示顶点数,$m$ 表示边数。
接下来的 $m$ 行中应给出每一条边的描述。每条边由三个整数 $a_i$、$b_i$、$c_i$ 组成($1 \leq a_i, b_i \leq n$,$a_i \neq b_i$,$1 \leq c_i \leq 10^9$)。任意两个顶点之间最多只能存在一条边。每条边必须且只能输出一次。图中必须至少存在一条以顶点 1 为端点的边。