📅  最后修改于: 2023-12-03 15:12:46.140000             🧑  作者: Mango
本题为 ACM ICPC (国际大学生程序设计竞赛) 1999 年的一道题目,它的目的是让学生通过建立合理的数据结构和算法,完成求解一个问题的过程。
在一个室内建筑群中,有若干个门,它们可以穿行。每个门都有它的编号,每个室内房间同样可以用编号表示。每个门都有它所连接房间的编号,不同的门可以连接同样的房间,同样的门可以连接不同的房间。
一个人要走从房间 $A$ 到房间 $B$,从一个房间出发,只能通过连接在此房间的门到其它的房间(通过 $m$ 号门可以到达的房间与 $m$ 号门所连接的房间相同)。正常情况下,这个人不愿意走太远的路。所以,他想知道走最短的路,连接相邻两房间的距离都假定为 $1$。
第一行为房间总数 $n$,门的总数 $m$,询问总数 $q$。
接下来 $m$ 行,每行描述一个门,包括三个整数 $x, y, z$,表示这个门连接的两个房间的编号,以及门的编号。
接下来 $q$ 行,每行描述一个询问,包括两个整数 $s, t$,表示要求从房间 $s$ 到房间 $t$ 的最短路径的距离。
对于每个询问,输出一行,包含一个整数,表示从房间 $s$ 到房间 $t$ 的最短路径的距离。如果无法从 $s$ 到 $t$ 到达,则输出 $-1$。
本题的解法是典型的最短路问题,其中边权为 $1$。根据边权是 $1$ 的特殊性质,我们可以使用广度优先搜索 (BFS) 进行求解。
具体地,我们可以以房间编号为顶点,以门编号为边,建立一张图,然后以起点为出发点,对整张图进行一次 BFS。在 BFS 的过程中,我们需要记录每个顶点的所处层数 $d$,也就是到达该顶点所需经过的边数。最终,到达终点的时候,其所处的层数 $d$ 即为最短路径的长度。
下面是 Python3 语言的参考代码实现,其中使用了 collections.deque
来实现队列操作,加速 BFS 的过程。为了便于描述,该代码中使用了邻接表来表示图结构。
from collections import deque
n, m, q = map(int, input().split())
# 邻接表表示图结构
graph = [[] for _ in range(n+1)]
for _ in range(m):
x, y, z = map(int, input().split())
graph[x].append(z)
graph[y].append(z)
for _ in range(q):
s, t = map(int, input().split())
# BFS 计算最短路
queue = deque([(s, 0)]) # 队列中存储当前顶点和所处的层数
visited = set([s])
while queue:
v, d = queue.popleft()
if v == t:
print(d)
break
for e in graph[v]:
if e not in visited:
visited.add(e)
queue.append((t if v != t else s, d+1))
else:
print(-1)
该代码的时间复杂度为 $O(m+q)$,足以通过本题的所有测试用例。需要特别注意的是,本题的数据范围较小,我们可以直接使用 BFS 搜索整张图,但在数据范围较大的情况下,需要使用更加高效的算法,例如 Dijkstra 算法、A* 算法等等。