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

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

题目介绍

本题是 “门|门 CS 1999” 的第 49 题,题目难度为普及+/提高。

该题目可以考察程序员对于图论算法的掌握程度,需要用到最短路算法。

题目描述

给出一张有 $N$ 个结点的有向图,每条边都有一个长度(即其所需花费的代价)。

请你求出从 $1$ 号结点到 $N$ 号结点的、长度最短的路径方案,输出路径上的所有结点(包括起点和终点)。

算法思路

该题目需要用到最短路算法,建议使用 Dijkstra 算法来求解。

  1. 创建一个表示距离的数组 $dist$,数组下标表示结点编号,数组值表示起点到该结点的最短距离,初始化为 $\infty$。

  2. 创建一个表示路径的数组 $path$,数组下标表示结点编号,数组值表示从起点到该结点的路径上的前一个结点,初始化为 $-1$。

  3. 创建一个表示结点是否已确定最短路的数组 $visited$,数组下标表示结点编号,数组值表示该结点是否已确定最短路,初始化为 $false$。

  4. 将 $dist[1]$ 初始化为 $0$,表示起点到自身的距离为 $0$。

  5. 创建一个小根堆 $pq$,将起点 $1$ 加入小根堆中,堆中元素为结点编号和最短距离的一对二元组。

  6. 然后将 $pq$ 中的堆顶元素弹出,表示选出了当前距离起点最短的结点 $u$,并将其设为已确定最短路。

  7. 对 $u$ 的所有出边进行松弛操作。如果 $dist[v] > dist[u] + w(u,v)$,则说明从起点到 $v$ 经过 $u$ 可以更新 $dist[v]$ 和 $path[v]$,同时将 $v$ 加入 $pq$。

  8. 重复步骤 6 和步骤 7 直到 $pq$ 为空。

  9. 根据 $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 算法的掌握程度。需要熟练掌握最短路算法的实现细节,才能顺利地解决本题。