📜  门|门 CS 1999 |第 60 题(1)

📅  最后修改于: 2023-12-03 15:12:46.140000             🧑  作者: Mango

门|门 CS 1999 | 第 60 题

本题为 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* 算法等等。