赞
踩
Dijkastra是常见的求单源最短路的算法,这里将介绍两种最短路的写法。
算法流程:
原因(理论证明):
为什么?我们使用反证法来证明:
Python代码:
n, m = map(int, input().split()) graph = [[999999] * (n+1) for _ in range(n+1)] for i in range(m): a,b,d = map(int, input().split()) graph[a][b] = min(graph[a][b], d) # 是否成为了最短路径点 st = [False] * (n+1) # 当前最短距离 dis = [999999] * (n+1) dis[1] = 0 for i in range(1, n+1): t = -1 # 寻找未被拓展的最短的点 for j in range(1, n+1): # 首先要没有被拓展,其次最短 if not st[j] and (t == -1 or dis[j] < dis[t]): t = j # 找到了当前可以拓展的节点t,加入并拓展节点t st[t] = True for j in range(1, n+1): dis[j] = min(dis[j], dis[t]+graph[t][j]) if dis[n] != 999999: print(dis[n]) else: print(-1)
最简单版本的Dijkstra还存在可以优化的地方,在我们每次寻找更新之后,当前可到达的点集中距离最短的那个点时候,每次都需要遍历一遍所有未得到最短距离的点,这个过程是O(n)的,我们可以使用最小堆,来将时间复杂度简化为O(logn),每次只需要取出堆顶元素即可。
from collections import defaultdict import heapq graph = defaultdict(list) n, m = map(int, input().split()) st = [False] * (n+1) dis = [-1] * (n+1) for i in range(m): a,b,d = map(int, input().split()) # 用二元组存 graph[a].append((d, b)) # 首先加入节点1,距离为0 q = [(0, 1)] while q: # 弹出堆顶元素,一定是当前非已知最短距离点集中最小的 t = heapq.heappop(q) d = t[0] node = t[1] # 如果t已经计算过最短路径,跳过 if st[node]: continue # 没有被计算过,设置为最短并且拓展 dis[node] = d st[node] = True for dis_, node_ in graph[node]: if not st[node_]: heapq.heappush(q, (d+dis_, node_)) print(dis[n])
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。