📜  门|门CS 2013 |问题 26(1)

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

门|门CS 2013 |问题 26

这道题主要考察图论的知识,具体来说是最短路算法。

问题描述

有 $n$ 个城市和 $m$ 条双向道路。第 $i$ 条道路连接 $u_i, v_i$ 两个城市,并且需要 $w_i$ 的代价。每个城市都有一个传送门,传送门之间互相连通,传送门的代价为 $0$。同时,从一个城市到另一个城市可以经过传送门,也可以经过道路。

给定起点 $s$ 和终点 $t$,找到从 $s$ 到 $t$ 的最短路径并输出其长度。

解题思路

我们可以把传送门看作一种特殊的边,其权值为 $0$。这就将传送门和道路统一起来,从而可以用最短路算法处理。

我们可以使用 Dijkstra 算法或者 Bellman-Ford 算法来解决本题。这里我选择使用 Dijkstra 算法。

事实上,Dijkstra 算法离 Bellman-Ford 算法并不远,本质上是一样的,只是 Dijkstra 算法基于贪心策略,每次选择当前距离起点最短的点来更新相邻的点。而 Bellman-Ford 算法则采用了 dp 的思想,从起点到终点至多有 $n-1$ 条边,我们通过反复利用这些边来逼近最短路径。

代码实现

这里给出 Dijkstra 算法的代码实现。首先需要按照题目输入定义好邻接表,然后按照下面的代码来实现。设 $n$ 表示节点数,$m$ 表示边数。

import heapq


def dijkstra(graph, s, t):
    n = len(graph)
    dist = [float('inf')] * n
    dist[s] = 0
    heap = [(0, s)]

    while heap:
        cost, u = heapq.heappop(heap)
        if dist[u] != cost:
            continue
        for v, w in graph[u]:
            if dist[v] > cost + w:
                dist[v] = cost + w
                heapq.heappush(heap, (dist[v], v))

    return dist[t]


if __name__ == '__main__':
    n, m = map(int, input().split())
    graph = [[] for _ in range(n)]
    for i in range(m):
        u, v, w = map(int, input().split())
        graph[u - 1].append((v - 1, w))
        graph[v - 1].append((u - 1, w))

    s, t = map(int, input().split())
    print(dijkstra(graph, s - 1, t - 1))

注:此处给出的代码使用了 Python 语言实现,最短路算法的实现也是一种常见的堆优化版 Dijkstra 算法,属于「特殊的」 Dijkstra 算法。

总结

本题是一道经典的图论问题,主要考察了最短路算法的知识。由于传送门和道路权值的差异,使得这道题变得更加丰富多彩,让我们在解题的过程中感受到了算法的魅力。