📜  门|门 IT 2008 |第 30 题(1)

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

门|门 IT 2008 | 第 30 题

题目描述

在一张无向图中,找到两个点之间的路径,使得路径上的边权之和最小,输出路径的长度和路径上的边。

输入格式

输入包含三行,第一行包含两个整数 $n,m$,表示无向图的节点数和边数。节点编号从 $1$ 至 $n$,边从 $1$ 至 $m$ 编号。

第二行包含 $m$ 个整数 $u_i,v_i,w_i$,表示第 $i$ 条边连接节点 $u_i$ 和 $v_i$,边权为 $w_i$。

第三行包含两个整数 $s,t$,表示起点和终点。

输出格式

输出包含两行,第一行包含一个整数 $len$,表示路径的长度。第二行包含若干个整数,表示路径上的边。

样例输入
4 5
1 2 1
1 3 3
1 4 2
2 3 1
3 4 1
1 4
样例输出
3
1 2 4
题解

该题需要使用最短路算法求解,这里推荐使用 Dijkstra 算法。Dijkstra 算法可以在无负权边的情况下求解最短路问题。

算法步骤如下:

  1. 将起点到各个点的距离初始化为无穷大,起点到起点的距离为 $0$。
  2. 以起点为起点,建立优先队列。
  3. 首次循环:从队列中取出距离起点最近的点,并更新其周围点的距离。
  4. 循环直到队列为空,即所有点的最短路径都被计算出来了。

参考代码如下(使用 Python 语言实现):

import heapq

n, m = list(map(int, input().split()))

edges = [[] for _ in range(n + 1)]
for i in range(m):
    u, v, w = list(map(int, input().split()))
    edges[u].append((v, w))
    edges[v].append((u, w))

s, t = list(map(int, input().split()))

dist = [float('inf')] * (n + 1)
dist[s] = 0
path = [-1] * (n + 1)

heap = [(0, s)]
while heap:
    d, u = heapq.heappop(heap)
    if d > dist[u]:
        continue
    for v, w in edges[u]:
        if dist[v] > d + w:
            dist[v] = d + w
            path[v] = u
            heapq.heappush(heap, (dist[v], v))

# 输出最短距离
print(dist[t])

# 输出最短路径
result = []
while t != -1:
    result.append(t)
    t = path[t]
result.reverse()
print(' '.join(str(x) for x in result))

以上算法的时间复杂度为 $O(m\log{m})$,空间复杂度为 $O(n+m)$。