title: Dijistra
date: 2023-11-16 20:32:49
tags: algorithm
单源最小路径问题
问题描述
单源最小路径问题描述了一个n结点的有向图G中一个点v0到各个结点的最小路径问题。如图:
Dijistra法利用贪心选择性质和最优子结构找到局部最优解来保证整体最优解,下面我们来介绍一下Dijistra法。
Dijistra算法
假设已经构造i条最短路径,下一条生成的路径是下一条的最短路径。
描述最短路径的生成规则:按照非降次序依次生成v0到个节点的路径:
设集合S是已经生成v0到各节点的最短路径的结点集合,设u是S外一点,dist(u)是经过S中结点,且在u结点结束的路径的长度**。
- 设w是从v0到u的路径上的结点,由于到u的路径一定经过S中的结点,根据生成规则,按非降次序生成最小路径,所以w一定在S集合中,所以在v0到u的路径上的点都已经生成最小路径;
- 生成的下一条路径的终点u是S外dist(u)最小的结点(按非降次序);
- 如果找到这样的u且生成了从v0到u的最短路径,将u加入集合S。此时从v0经过u终点为S外一点u的最小路径可能会变小,因为可能经过u到w的路径更短,这时dist(w) = min(dist(w),dist(u) + c(u,w))。
代码
#Dijistra法解决单源最小路径问题
#描述一个邻接矩cost(n,m)代表有向图中n到m之间的距离,没有连线的为无限大
#v是存放结点的数组,n是结点的个数,dist是从v0到某一点的最短路径
def SHORT-PATH(v,cost,dist,n):
S = [False]*n;
for i in range(n):
dist[i] = 0
#false代表不在S里,true代表在S里
s[i] = false
s[v] = True
dist[v] = 0
for num in range(2,n-1):
#按非降次序选入不在S中的(还没有生成最小路径的)dist[x],找到dist[x]最小的结点x
u = min((i for i in range(n) if not s[i]),key = lambda x:dist[x])
s[u] = true
for w in range(n):
if not s[w]:
dist[w] = min(dis[w],dist[u] + cost[u][w])
例题
迭代 | 选取的结点 | S | dist(1) | dist(2) | dist(3) | dist(4) | dist(5) | dist(6) | dist(7) |
---|---|---|---|---|---|---|---|---|---|
初始化 | - | 1 | 0 | 20 | 50 | 30 | MAX | MAX | MAX |
1 | 2 | 1,2 | 0 | 20 | 45 | 30 | MAX | 90 | MAX |
2 | 4 | 1,2,4 | 0 | 20 | 45 | 30 | 85 | 90 | MAX |
3 | 3 | 1,2,3,4 | 0 | 20 | 45 | 30 | 70 | 90 | MAX |
4 | 5 | 1,2,3,4,5 | 0 | 20 | 45 | 30 | 70 | 80 | 140 |
5 | 6 | 1,2,3,4,5,6 | 0 | 20 | 45 | 30 | 70 | 80 | 130 |
建议手推一遍,发现dist[u]来自要么是上一个生成的最小路径加上上一个最小路径的终点到u的距离和,要么是从v0到u的距离dist[u](不连通就是无限大)。