当今世界上各类程序设计竞赛层出不穷。而设计一场好比赛绝非易事,比如给题目设计测试数据就是一项挑战。一组好的测试数据需要对不同的程序有区分度:满足所有要求的程序自然应该得到满分,而那些貌似正确的程序则会在某些特殊数据上出错。
在本题中,你在比赛中的角色反转啦!作为一名久经百战的程序员,你将帮助 Happy Programmer Contest 的命题委员会设计这次比赛的测试数据。本次比赛命题委员会选择了两个图论问题,分为
- 输入
对于源程序 一定不会出现超出时间限制(TLE)的问题。 - 输入
一定会导致源程序 产生超出时间限制的问题。
此外,命题委员喜欢较小规模的测试数据,希望测试数据最好能够包含不超过
本题中只关心源程序
命题委员会选择了单源最短路(SSSP)以及一个被称之为神秘问题(Mystery)的两个图论问题来作为比赛的题目。我们将命题委员会完成的伪代码列在了附录中,而具体的 C、C++ 和 Pascal 源程序见源程序下载。
子任务
参见下表。表中每一行描述了一个子任务。其中前六个子任务与单源最短路相关,子任务 7,8 与神秘问题相关。每个任务所占分数见下表。
测试点编号 | 分数 |
目标 |
问题 | 源程序 |
源程序 |
---|---|---|---|---|---|
1 | 3 | SSSP | ModifiedDijkstra | FloydWarshall | |
2 | 7 | SSSP | FloydWarshall | OptimizedBellmanFord | |
3 | 8 | SSSP | OptimizedBellmanFord | FloydWarshall | |
4 | 17 | SSSP | FloydWarshall | ModifiedDijkstra | |
5 | 10 | SSSP | ModifiedDijkstra | OptimizedBellmanFord | |
6 | 19 | SSSP | OptimizedBellmanFord | ModifiedDijkstra | |
7 | 11 | Mystery | Gamble1 | RecursiveBacktracking | |
8 | 25 | Mystery | RecursiveBacktracking | Gamble2 |
对于每个子任务,你的程序给出的输入
也就是说,如果你的测试数据
你需要把你的
- 如果未提交数据,则不得分
- 若数据不满足输入格式要求,则不得分
- 对源程序
运行输入,若发生超时现象,则不得分 - 对源程序
运行输入,若发生超时现象,则按照前文所述的公式给出该测试点的分数。
题目提供的所有源代码均会维护一个计数器来统计程序的操作次数。在源程序的运行过程中,当该计数器超过了
问题 1:单源最短路(SSSP)
给定一个带权有向图
问题 1 输入输出格式
输入数据包含两部分,其中第一部分使用邻接表来描述带权有向图
数据第一部分的第一行包含一个整数
接下来
数据第二部分的第一行包含一个整数
接下来
同一行中任意两个相邻的整数均需要至少一个空格将他们分开。除此之外,数据还需满足如下条件:
是一个非负整数- 所有询问中的起点
都不能达到任何一个负权圈。
程序将会输出
问题 1 样例
input
3 2 1 4 2 1 0 1 1 2 2 0 1 1 0
output
3 1000000000 The value of counter is: 5
问题 2:神秘问题
给定一个包含
问题 2 输入输出格式
输入数据的第一行包含两个整数
接下来
- 对于所有的边
,有 ,不会重复描述一条边。
程序将在第一行输出
问题 2 样例
input
4 5 0 1 0 2 0 3 1 2 2 3
output
3 0 1 2 1 The value of counter is: 18
附录:伪代码
接下来是我们提供的所有程序的伪代码;变量 counter 近似描述出了程序的运行时间。评测时将会使用这些伪代码的 C++ 版本来进行评测。
FloydWarshall
// pre-condition: the graph is stored in an adjacency matrix M
counter = 0
for k = 0 to V-1
for i = 0 to V-1
for j = 0 to V-1
increase counter by 1;
M[i][j] = min(M[i][j], M[i][k] + M[k][j]);
for each query p(s,t)
output M[s][t];
OptimizedBellmanFord
// pre-condition: the graph is stored in an adjacency list L
counter = 0
for each query p(s,t);
dist[s] = 0; // s is the source vertex
loop V-1 times
change = false;
for each edge (u,v) in L
increase counter by 1;
if dist[u] + weight(u,v) < dist[v]
dist[v] = dist[u] + weight(u,v);
change = true;
if change is false // this is the ’optimized’ Bellman Ford
break from the outermost loop;
output dist[t];
ModifiedDijkstra
// pre-condition: the graph is stored in an adjacency list L
counter = 0;
for each query p(s,t)
dist[s] = 0;
pq.push(pair(0, s)); // pq is a priority queue
while pq is not empty
increase counter by 1;
(d, u) = the top element of pq;
remove the top element from pq;
if (d == dist[u])
for each edge (u,v) in L
if (dist[u] + weight(u,v) ) < dist[v]
dist[v] = dist[u] + weight(u,v);
insert pair (dist[v], v) into the pq;
output dist[t];
Gamble1
Sets X = V;
labels vertex i in [0..V-1] with i;
Sets counter = 0; // will never get TLE
Gamble2
Sets X = V;
labels vertex i in [0..V-1] with i;
Sets counter = 1000001; // force this to get TLE
RecursiveBacktracking
This algorithm tries
For each
Please check RecursiveBacktracking.cpp/pas to see the exact lines where the iteration counter is increased by