329. 矩阵中的最长递增路径c_图04---最短路径

在网络中,求两个不同顶点之间的所有路径 中,边的权值之和最小的那一条路径

  • 这条路径就是两点之间的最短路径(Shortest Path)
  • 第一个顶点为源点(Source)
  • 最后一个顶点为终点(Destination)

单源最短路径(single-source shortest paths)

给定带权图 G = <V,E>,其中每条边 (vi,vj ) 上的权 W[vi,vj ] 是一个 非负实数 。计算从任给的一个源点 s 到所有其他顶点的最短路径

79d96d61bf62e6d7922b3c918d8c7f79.png

无权图的单源最短路算法

按照递增(非递减)的顺序找出到各个顶 点的最短路(BFS)

86610824275f6b55898c5c3a84207a8d.png

James Bond 从孤岛跳上岸,最少需要跳多少步?

void 

dist[W] = S到W的最短距离

dist[S] = 0

path[W] = S到W的路上经过的某顶点

有权图的单源最短路算法

按照递增的顺序找出到各个顶点的最短路(Dijkstra算法)

8e5767ba60f6f786ad6fbd2697ff9b72.png

Dijkstra算法基本思想

把所有结点分成两组

第一组 U 包括已确定最短路径的结点
第二组T= V–U 包括尚未确定最短路径的结点

按最短路径长度递增的顺序逐把第二组的结点加到第一组中 ,

直至从 源点

出发可达结点 都包括进第一组中

Dijkstra 算法

令U={源点

+ 已经确定了最短路径的顶点
}

然后不断从集合T中选取到顶点

路径长度最短的顶点v加入到集合U中,集合U每加入一个新的顶点v,都要修改顶点
到集合T中剩余顶点的
最短路径长度值。不断重复此过程,直到集合T的顶点全部加入到U中或无通路为止。

算法过程

(1) 引进一个辅助向量Dist,它的每个分量

表示当前所找到的从开始点
到每个终点
的最短路径的长度。它的初态为:若从
有弧,则Dist[i]为弧上的权值;否则置 Dist[i]为∞。显然:

Dist[j]表示的就是从

出发的长度最短的一条最短路径。此路径为

对任一未收录的顶点v,定义dist[v]为

到v的最短路径长度,但该路径仅经过U中的顶点。即路径
的最小长度

若路径是按照递增(非递减)的顺序生成的,则

  • 真正的最短路必须只经过U中的顶点(为什么?)
  • 每次从未收录的顶点中选一个dist最小的收录(贪心)
  • 增加一个v进入U,可能影响另外一个w的dist值!
dist[w] = min{dist[w], dist[v] + <v,w>的权重}

47e531bc67df8e7e87607afebb0908db.png

6d163eff2f6112260ebef401c9aecfa7.png

1cb1091779331ab3846d44d6cdddf82b.png

1、初始U={

}

5ef6e840109f554774d0c86a34b64688.png

83edfa389b23f336372be19df9cf26f5.png

2、从顶点

到顶点
的最短距离为{50,10,∞,∞,∞},其最短路径为10,
进入集合U,即U={
}。

50413f2b30e648c08e2f6a08e599be9c.png

6b82a9734429051d0b970c56ec0ecc42.png
V_2 进入集合U

3、求次短路径的方法。

例如,当U={

}后,
到其它顶点
的最短路径改变为{50,25,∞,∞},从中继续选取最小值,以此类推,直到全部元素都加到U中去。

ee380bffe15b9257ea75ff701ff73ea9.png

92ebc65bbfb8c15ee32d387f21f53e58.png

cad0d0edc62e3dadb331ff1eff7a1203.png

6294b1e7cc7936a879b862b788c34cb6.png

f4ebd6af12865b3b4e4a62f93349229d.png

2761fe8a8124623ebb2d3ecba40238f5.png

算法描述:

(1)假设用带权的邻接矩阵ed 来表示带权有向图

(2)选择

,使得

Dist[j]:从

出发到j的最短路径长度。

(3)修改从

出发到集合T 上任一顶点
可达的最短路径长度。如果

则修改Dist[k]为Dist[k]=Dist[j]+ed[j][k],重复操作(2)、(3)共n-1次。由此求得从
到图上其余各顶点的最短路径是路径长度递增的序列。

Dijkstra单源最短路径迭代过程

4c71279b9771bb306397786f1b363e1b.png

Dijkstra单源最短路径算法

class 
void 

方法1:直接扫描所有未收录顶点

对于稠密图效果好

方法2:将dist存在最小堆中

更新dist[w]的值

对于稀疏图效果好

Dijkstra算法时间代价分析

每次改变D[i].length

不删除,添加一个新值(更小的),作为堆中新元素。旧值被找到时,该结点一定被标记 为VISITED,从而被忽略

在最差情况下,它将使堆中元素数目由

增加到
,总的时间代价

Dijkstra算法

是否支持

  • 有向图、无向图
  • 非连通
  • 有回路的图
  • 权值为负

如果不支持

  • 则修改方案?

针对有向图 (且“有源”)

  • 若输入无向图?
  • 照样能够处理 (边都双向)

对非连通图,有不可达

  • 没有必要修改

支持回路

支持负权值?

Dijkstra算法不支持负权值

如果存在总权值为负的回路,则将出现权 值为

的情况

e6d45634fd8047aa99a6f9383f955a08.png

如果不存在负权回路呢?

Dijkstra算法不受负权边的影响吗?

即使不存在负的回路,也可能有在后面出现的负权值, 从而导致整体计算错误

主要原因是 Dijkstra 算法是贪心法,当作最小取进来后,不会返回去重新计算

d1588714f0de6f29d9c958225e3c9ae0.png

持负权值的最短路径算法

• Bellman-Ford 算法

• 参考书 MIT “Introduction to Algorithms”

• SPFA 算法

多源最短路径问题:

求任意两顶点间的最短路径

方法1:直接将单源最短路算法调用|V|遍

对于稀疏图效果好

方法2:

对于稠密图效果好,Floyd算法

每对结点间的最短路径

• 还能用 Dijkstra 算法吗?

• 以每个结点为起点,调用 n 次 Dijkstra 算法

void 

多源最短路算法

Floyd 算法

= 路径{
}的最小长度

即给出了 i 到 j 的真正最短距离

最初的
是什么?

已经完成,递推到
时:
  1. 或者k
    最短路径{
    },则
    =
  2. 或者k
    最短路径{
    },则该路径必定由两段最短路径组成:

Floyd算法求每对结点之间的最短路径

用相邻矩阵 adj 来表示带权有向图

基本思想:

初始化

为相邻矩阵 adj

在矩阵

上做 n 次迭代,递归地产生一个矩阵序列

其中经过第k次迭代,

的值等于从结点
到结点
路径上
所经过的结点序号不大于
的最短路径长度

动态规划法

最短路径组合情况分析

由于第

次迭代时已求得矩阵
,那么从结点
中间结点的序号不大于
的最短路径有两种情况:

一种是中间不经过结点

,那么此时就有

另中间经过结点

,此时
, 那么这条由结点
经过
到结点
的中间结点序号不大于
的最短路径由两段组成

用弗洛伊德算法求下图所示的带权有向图G的每一对顶点间的最短路径及路径长度的过程如下。由矩阵path可知任何一对顶点间最短路径经过结点。

73eda5d377698d8e24130412487329b7.png
图 10

图 10:当任意两点之间不允许经过第三个点时,这些点之间最短路程就是初始路程:adj矩阵,最短路径经过结点是path矩阵。

只允许经过

号顶点,求任意两点之间的最短路程.

,所以更新adj矩阵为
,最短路径经过结点是path矩阵。

6ad9a00c24f32e73aaab120a1dbba1d6.png
图 11

图 11:只允许经过

号顶点,求任意两点之间的最短路程.

,所以更新
矩阵为
,最短路径经过结点是path矩阵。

4beb9db66b2bd832193ef56e1dadea2d.png
图 12

图 12:只允许经过

号顶点,求任意两点之间的最短路程.

,所以更新
矩阵为
,最短路径经过结点是path矩阵。
void 

python:

import 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值