算法与数据结构课件——最短路径
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
顶点0 0 0
顶点1 -
顶点2 -
顶点3 -
顶点4 -
索引堆:
1
10 0 100
1 30 4
50 10
60
2 20 3
0
1
2
3
4
0
-
-
-
-
Dijkstra示例
10 0 100
1 30 4
50 10
60
2 20 3
顶点0 0 0
顶点1 -
顶点2 -
顶点3 -
顶点4 -
索引堆:
10
1 30 3
0
1
2
3
• Dijkstra算法求解从顶点v0出发到 其它各顶点最短路径。
• 按路径⻓度递增的次序产⻓最短路 径,该算法假设所有边的权都⻓ 于等于零。
边上权值非负情形的单源最短路径问题
问题的提法: 给定一个带权有向图D与源点 v,求从 v 到 D中其它顶点的最短路径。限定各边上的权值大于或等于 0。
为求得这些最短路径, Dijkstra提出按路径长度的递增次序 , 逐步产生最短路径的算法。首先求出长度最短的一条 最短路径,再参照它求出长度次短的一条最短路径,依 次类推,直到从顶点v到其它各顶点的最短路径全部求出 为止。
0
1
2
3
4
0
10
50
30
90
Dijkstra示例
顶点0 0 0
顶点1 10 -
顶点2 50 -
顶点3 30 -
顶点4 60 -
索引堆:
4
10 0 100
2
1 30 4
50 10
60
0
0
2 20 3
1
2
3
4
10
50
30
60
作业:基于数组、堆实现Dijkstra算法
DijksHale Waihona Puke Baidura示例
顶点0 0 0
➢不能处理带负权环的图(因可以来回走一条负权边)
• 限制条件: • 要求图中不能包含权值总和为负值回路(负权值回路),
如下图所示。
4
0
1
2
6
3
2
-19
0->3: 2
0->1->2->3: 1
0->1->2->3->0: -7
Bellman-Ford算法思想
• 构造一个最短路径长度数组序列dist 1 [u], dist 2 [u], …, dist n-1 [u] (u = 0,1…n-1,n为点数)
顶点3 30 0->3
顶点2 60,50 1->2,3->2
顶点3 30 0->3
顶点4 -
顶点4 100 0->4 顶点4 100 0->4
顶点4 100,90 0->4,3->4
顶点4 100,90 0->4,3->4
Bellman-Ford算法
队列: 2
顶点0 0 0
顶点1 10 0->1
顶点2 60,50 1->2,3->2
顶点3 30 0->3
顶点3 30 0->3
顶点4 -
顶点4 100,50 0->4, 2->4
顶点4 40 2->4
顶点4 40 2->4
顶点4 40 2->4
Bellman-Ford算法
10 0 100 1 30 4
50 -10 60
23
20
队列: 0
顶点0 0 0
队列: 1, 3, 4
顶点0 0 0
4
0
-
-
-
-
Dijkstra示例
顶点0 0 0
顶点1 10 -
顶点2 60 -
顶点3 30 -
顶点4 100 -
10 0 100
1 30 4
50 10
60
2 20 3
索引堆:
0
0 0
1
30 3
4 100
1
2
10
-
3
4
30
100
Dijkstra示例
顶点0 0 0
顶点1 10 -
顶点2 60 -
顶点3 30 -
短路径长度; ➢ ...... ➢ dist n-1 [u]为从源点s出发最多经过不构成负权值回路的n-1次relax到达终点u的
最短路径长度;
• 算法的最终目的是计算出dist n-1 [u],为源点v到顶点u的最短 路径长度。
dist k [u]的计算
• 设已经求出 dist k-1 [u] , u = 0, 1, …, n-1,即从源点s经过最多 不构成负权值回路的k-1次relax到达终点u的最短路径的长度
edgeTo[w]: s到w的已知最短路径上的最后一条边 重庆-成都 =》 西安-成都
• 如果边e = v→w 给出了一条经通过v到达w的更短路径
• 更新distTo[w]和edgeTo[w]
最短路径-最优性性质
• 对于有向带权图G, distTo[ ]表示s到各节点的路径,有:
➢ distTo[s] = 0 ➢ 对于其他各个节点, distTo[v]表示某条从s到v的路径长度(对于不可达的节
顶点3 30 0->3
顶点4 100,90 0->4,3->4
10 0 100
1 30 4
50 -10 60
23
20
队列: 4
顶点0 0 0
顶点1 10 0->1
顶点2 60,50 1->2,3->2
顶点3 30 0->3
顶点4 100,90,40 0->4,3->4,2->4
队列:
顶点0 0 0
顶点1 10 0->1
• 递推公式(求顶点u到源点s的最短路径):
➢ dist 1 [u] = adj[s][u]; ➢ dist k [u] = min{ dist k-1 [u], min{ dist k-1 [j] + adj[j][u] } }, j=0,1,…,n-1,j≠u
Bellman-Ford算法
• 算法SP(G, s):
假设 S 是已求得的最短路径的终点的集合,则可证明:下 一条最短路径必然是从v0 出发,中间只经过 S 中的顶点便 可到达的那些顶点vx (vxV-S )的路径中的一条。
每次求得一条最短路径后, 其终点vk 加入集合S,然后对所 有的vi V-S,修改其 dist[i]值。
Dijkstra算法可描述如下:
10 0
1
30
50 2 20
100 10 4
60 3
➢distTo[0] = 0
➢distTo[1] = 10 ➢distTo[2] = 50 ➢distTo[3] = 30 ➢distTo[4] = 90
第1步是选择0节点,对它的所出边进行松弛 第2步是选择1节点,对它的所出边进行松弛 第3步是选择3节点,对它的所出边进行松弛 。。。
顶点4 100 -
10 0 100
1 30 4
50 10
60
2 20 3
索引堆:
3 30
1
100
4
2 60
0
1
2
3
4
0
10
60
30
100
Dijkstra示例
顶点0 0 0
顶点1 10 -
顶点2 50 -
顶点3 30 -
顶点4 90 -
索引堆:
2
10 0 100
3
4
1 30 4
50 10
60
2 20 3
— Dijkstra算法
➢ 边上权值为任意值的单源最短路径问题
— Bellman Ford算法
➢ 所有顶点之间的最短路径 (动态规划O(n^3))
— Floyd算法
最短路径相关数据结构
• 目标:找出从s节点到其他所有节点的最短路径.
• 路径:s到所有节点的最短路径树(SPT)必定存在
• 可以用2个数组来表示SPT:
50 10 60 edgeTo[3] = 0,反过来排列,
2 20 3
得到路径 0, 3, 2, 4,这就是源 点0到终点4的最短路径。
Dijkstra示例
顶点0 0 0
顶点1 -
顶点2 -
顶点3 -
顶点4 -
索引堆:
0
10 0 100
1 30 4
50 10
60
2 20 3
0
1
2
3
4
0
-
-
-
-
Dijkstra示例
顶点2 60,50 3->2
点,该值为无穷大) ➢ distTo[v]是最短路径,当且仅当:对于任意一条v到w的边e,都满足:
distTo[w] ≤ distTo[v] + e.weight()
最短路径通用算法
• 算法SP(G, s):
➢ distTo[s] 初始化为 0 ➢ 对于其他各个节点, distTo[v]初始化为无穷大 ➢ 重复如下操作:松驰G中的任意边,直到不存在有效边为止
算法与数据结构
最短路径
目录
最短路径介绍 Dijkstra算法 Bellman Ford算法
最短路径问题
• 最短路径问题:如果从图中某一顶点(称为源点)到达另一顶点(称为终 点)的路径可能不止一条,如何找到一条路径使得沿此路径上各边上的 权值总和达到最小。(有向带权图)
• 问题解法
➢ 边上权值非负情形的单源最短路径问题 (s -> 图上其他节点的最短路径)
➢ distTo[v]: s到v的最短路径,100
S-> X->W ->V s
➢ edgeTo[v]:s到v的最短路径上的最后一条边 x
s
w
x
w
v
v
边松驰 - Edge Relax
• 松驰边:e = v -> w (西安到成都的高铁是没有开通: 700)
➢ distTo[v]: s到v的已知最短路径 (北京到西安的距离: 800) ->1500 ➢ distTo[w]: s到w的已知最短路径 (北京到成都的最短距离(高铁)2000)
➢ dist 1 [u]为从源点s到终点u的最多经过1次relax的最短路径长度,并有dist 1 [u] =adj[s][u];
➢ dist 2 [u]为从源点s最多经过两次relax到达终点u的最短路径长度; ➢ dist 3 [u]为从源点s出发最多经过不构成负权值回路的三次relax到达终点u的最
• 实现:怎么样选择边来松驰?
➢ Dijkstra's algorithm (nonnegative weights) ➢ Bellman-Ford algorithm (no negative cycles)
目录
最短路径介绍 Dijkstra算法 Bellman Ford算法
Dijkstra算法
顶点0 0 0
顶点0 0 0
顶点0 0 0
顶点1 -
顶点1 10 0->1
顶点1 10 0->1
顶点1 10 0->1
顶点1 10 0->1
顶点2 -
顶点3 -
顶点2 60,50 1->2, 3->2
顶点3 30 0->3
顶点2 50 3->2
顶点3 30 0->3
顶点2 50 3->2
顶点2 50 3->2
顶点1 10 -
顶点2 50 -
顶点3 30 -
顶点4 60 -
索引堆:
10 0 100
4
1 30 4
50 10
60
0
0
2 20 3
1
2
3
4
10
50
30
60
目录
最短路径介绍 Dijkstra算法 Bellman Ford算法
Bellman-Ford算法
• 解决含负权边的带权有向图的单源最短路径问题
➢ distTo[s] 初始化为 0 ➢ 对于其他各个节点, distTo[v]初始化为无穷大 ➢ 重复V-1次:依次松驰G中的各条边
Bellman-Ford算法
10 0 100
边:
1 30
0->1
4
0->3
0->4
50 -10
60
1->2 2->4
23
3->2 3->4
20
顶点0 0 0
顶点0 0 0
队列: 3, 4, 2
顶点0 0 0
队列: 4, 2
顶点0 0 0
队列: 2
顶点0 0 0
顶点1 -
顶点1 10 0->1 顶点1 10 0->1
顶点1 10 0->1
顶点1 10 0->1
顶点2 顶点2
顶点2 60 1->2
顶点3 -
顶点3 30 0->3
顶点3 30 0->3
顶点2 60,50 1->2,3->2
④ 判断:若 S = V, 则算法结束,否则转 ②。
Dijkstra算法中各辅助数组的最终结果
序号 顶点 1 顶点 2
Dist
10
-,60,50
edgeTo
0
3
顶点 3 30 0
顶点 4 60 2
10 0 100 从表中读取源点0到终点v的最
1 30
4 短路径的方法 : 举顶点4为例 edgeTo[4] = 2 edgeTo[2] = 3
10 0
1
30
50 2
20
100 10 4
60 3
0 1 2 34 0 10 50 30 60
4 2
3
引入辅助数组dist。它的每一个分量dist[i]表示当前找到的 从源点 v0到终点 vi 的最短路径的长度。初始状态: 若从源点v0到顶点 vi 有边, 则dist[i]为该边上的权值; 若从源点v0到顶点 vi 无边, 则dist[i]为 。
① 初始化: S ← { v0 }; dist[j] ← Edge[0][j], j = 1, 2, …, n-1; // n为图中顶点个数
② 求出最短路径的长度: dist[k] ← min { dist[i] }, i V- S ; //s->k就是
最短距离 S ← S U { k };
③ 修改: dist[i] ← min{ dist[i], dist[k] + Edge[k][i] }, 对于每一个 i V- S ;
10 0
1
30
50 2 20
100 10 4
60 3
Dijkstra逐步求解的过程
源点 终点 最短路径
路径长度
v0 v1 (v0,v1)
10
v2
(v0,v1,v2) (v0,v3,v2) ,60,50
v3 (v0,v3)
30
v4 (v0,v4) (v0,v3,v4) (v0,v3,v2 ,v4) 100,90,60