📅  最后修改于: 2023-12-03 15:42:21.073000             🧑  作者: Mango
本题是 “门|门 CS 1999” 的第 49 题,题目难度为普及+/提高。
该题目可以考察程序员对于图论算法的掌握程度,需要用到最短路算法。
给出一张有 $N$ 个结点的有向图,每条边都有一个长度(即其所需花费的代价)。
请你求出从 $1$ 号结点到 $N$ 号结点的、长度最短的路径方案,输出路径上的所有结点(包括起点和终点)。
该题目需要用到最短路算法,建议使用 Dijkstra 算法来求解。
创建一个表示距离的数组 $dist$,数组下标表示结点编号,数组值表示起点到该结点的最短距离,初始化为 $\infty$。
创建一个表示路径的数组 $path$,数组下标表示结点编号,数组值表示从起点到该结点的路径上的前一个结点,初始化为 $-1$。
创建一个表示结点是否已确定最短路的数组 $visited$,数组下标表示结点编号,数组值表示该结点是否已确定最短路,初始化为 $false$。
将 $dist[1]$ 初始化为 $0$,表示起点到自身的距离为 $0$。
创建一个小根堆 $pq$,将起点 $1$ 加入小根堆中,堆中元素为结点编号和最短距离的一对二元组。
然后将 $pq$ 中的堆顶元素弹出,表示选出了当前距离起点最短的结点 $u$,并将其设为已确定最短路。
对 $u$ 的所有出边进行松弛操作。如果 $dist[v] > dist[u] + w(u,v)$,则说明从起点到 $v$ 经过 $u$ 可以更新 $dist[v]$ 和 $path[v]$,同时将 $v$ 加入 $pq$。
重复步骤 6 和步骤 7 直到 $pq$ 为空。
根据 $path$ 数组反推出从起点到终点的路径,并输出路径上的所有结点。
以下是 Python 实现 Dijkstra 算法的代码:
import heapq
def dijkstra(adj, start, end):
n = len(adj)
dist = [float("inf")] * n
path = [-1] * n
visited = [False] * n
dist[start] = 0
pq = []
heapq.heappush(pq, (0, start))
while pq:
(d, u) = heapq.heappop(pq)
if visited[u]:
continue
visited[u] = True
for (v, w) in adj[u]:
if dist[v] > dist[u] + w:
dist[v] = dist[u] + w
path[v] = u
heapq.heappush(pq, (dist[v], v))
if dist[end] == float("inf"):
return []
res = []
u = end
while u != -1:
res.append(u)
u = path[u]
return res[::-1]
本题考察了程序员的图论算法实现能力,同时也考察了程序员对 Dijkstra 算法的掌握程度。需要熟练掌握最短路算法的实现细节,才能顺利地解决本题。