最短路径经典算法其一Dijkstra
前言
今天我们来讲讲图搜索最短路径,这里的最短路径包含了从一个节点到达另一个节点需要考虑之间的距离或者时间消耗,即从起点到达终点所需的时间(或者其他形式的消耗)最少,不同于我们之前提到的迷宫搜索类最短路径——通路上的节点数量更少(即假设节点间的距离都是1)
Ps: 原文章系博主的微信推文,有一些会有前后联系,现陆续搬运到优快云~
一、算法原理讲解
实现语言:Python
对于上面的问题,我们看下面的这张图:
这个时候我们好像需要去遍历图上的节点,常规BFS搜索得到的最短路径不一定是耗时最少的。
这里我们介绍经典的单源最短路径搜索算法——狄克斯特拉算法(Dijkstra’s algorithm)。单源的意思是说它可以得到指定的一个起点到达其他所有节点的最短距离。
本质上它是一个循环优化算法,在每个循环里,它完成下面的几个步骤:
1. 找到当前已知距离起点最短的节点,即可以最快到达的点2. 通过与该点连接的其他节点更新周围节点的距离开销,即起点到达这些周围节点的距离
以上面的图为例,我们来用图表示一下简单的算法流程:
首先最先知道的最短节点是起点本身,一开始我们要设置所有点之间都是无穷远,然后用已知的边来更新这些值,不过这里我给到的图示所有的边权重都有给出。从起点M开始,找到了A,B,N,并更新权重。
第二次循环开始,找到距离起点最近的点为B后,开始找和B相连的其他节点,记住这些节点不能是之前循环标记过的最近点,因为之前循环确定的最近点对这一轮更新其到起点的距离没有意义,它已经是最近的了。
我们可以看到符合条件的有A和N,接下来更新它们到起点的距离值。发现MB+BA< MA,即有更近的路可以从起点到达A点,所以更新MA的值,同样的更新MN的值。
第三次循环距离起点最近的点为A,找到与A相连的且还没被标记过的节点,只有N,但是MA+AN=10>MN=8,所以不更新MN的距离值。
下一次循环到达终点后即可退出,所以最终起点到达所有其他节点的最短距离都可以得到,也就包括起点到终点。
二、代码实现
def Dijkstra(directed=False):
"""
Functions: Implementation of Dijkstra using Python
Args:
directed: whether the graph is directed or not
return:
None
"""
# init distance
limit = 10000
# number of nodes, number of links, start_index, end_index
N, K, s, e = list(map(int, input().split()))
# graph mat
ad_mat = [[0 for i in range(N)] for j in range(N)]
# distance to start_node
Dis = [limit for i in range(N)]
# tags array
vis = [0 for i in range(N)]
# use links to fresh graph mat
for i in range(K):
u, v, w = list(map(int, input().split()))
ad_mat[u][v] = w
if directed == False:
ad_mat[v][u] = w
# init distance of