Single-source and All-pairs shortest paths

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

Problem:From a given source vertex s∈V, find the shortest-path weightδ(s,v) for all v∈V. If all edge weight w(u,v) are nonnegative(无负权值边), all shortest-path weights must exist.

Dijkstra algorithm(Greedy)
  1. Maintain a set S of vertices whose shortest-path distances from s are known
  2. At each step add to S the vertex v∈V-S whose distance estimate from s is minimal.
  3. Update the distance estimates of vertices adjacent to v.

Dijkstra算例:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
伪代码:
在这里插入图片描述

时间复杂度: Time=Θ(V.TEXTRACT-MIN+E.TDECREASE-KEY)
在这里插入图片描述
EXTRACT-MIN 是从数组(队列)中取出距离源点距离最短的顶点
DECREASE-KEY: 更新数组(队列)中顶点的距离

Bellman-Ford algorithm

这是一种处理存在负权值边的单源最短路径问题的算法。解决了Dijkstra无法求存在负权值边的问题。虽然其算法效率不高,但也有其特别的用处,其实现方式是通过m-1次迭代求出源点到终点不超过m条边构成的最短路径.一般情况下要求途中不存在负环。但是在边数有限制的情况下允许存在负环。因此Bellman-Ford 可用来判断负环
求解步骤:

  1. 初始化操作和Dijkstra算法一致,源点到自己的距离为0,其他点到源点的距离为正无穷。
  2. 第一次迭代:找到源点到各顶点不超过1条边的最短路径,更新距离。
    第二次迭代:找到源点到各顶点不超过2条边的最短路径,更新距离。

    依次类推,可迭代次数是无数次的,但是如果不存在负环,那么当迭代次数与边数-1相等时就保证了存在结果
    上述的实际操作是通过每次遍历(i=1~v-1)有向图中的每条边,对这条边的起点u和终点v以及边上的权值做如下判断,如果起点u的距离d+边上权值w(u,v)<终点v的距离d,则更新终点的距离d为起点u的距离d+边上权值w(u,v)。判断负环是在上述过程判断完之后,再次对每条边进行上述运算,如果存在边的距离(起点或终点)还能变小,说明存在负环,否则不存在负环.
    Bellman-Ford算例:
    在这里插入图片描述初始化序列号:
    在这里插入图片描述
    下面根据序号1~8条边依次做上面所述的判断,并更新每条边起始边的距离:
    在这里插入图片描述
    上述第一趟结束,下面开始第二,三趟…
    在这里插入图片描述
    伪代码:
    在这里插入图片描述
    时间复杂度: Time=O(VE)

All-pairs shortest paths(多源最短路径)

Problem Input: Digraph G=(V,E), where |V|=n, with edge-weight function w: E->R

Output: n*n matrix of shortest-path lengths δ(i,j) for all i,j∈V.

  1. 对于多源最短路径,可以根据单源最短路径求解(Dijkstra or Bellman-ford),无非是多循环几次,但效率还是很低的.
  2. dp求解:考虑图的n*n邻接矩阵A=(aij),定义d(m)ij =从 i 到 j 最多使用 m 个边的最短路径的权重
    在这里插入图片描述
其中m=1,2,…,n-1:  d(m)ij=mink{d(m-1)ik+akj} 
Relaxation:
   for k <-1 to n
       do if dij > dik + akj
            then dij = dik + akj
注意: 没有负权值边意味着:
    δ(i,j) = d(n-1)ij=d(n)ij=d(n+1)ij=…

示意图:
在这里插入图片描述

计算 C=A·B,其中 C、A 和 B 是 n*n 矩阵(k=1..n):
cij=∑aikbkj. 则:Time=Θ(n3) 使用标准算法。

我们映射“+”->“min”和“.”->“+”,也即aik·bkj = aik + bkj , aik + bkj = min {aik + bkj}
得到:cij=min k {aik+bkj},因此D(m)=D(m-1)“×”A。(“x”为上述的映射形式)

在这里插入图片描述

因此,我们可以计算
        D(1)=D(0)·A=A^1
        D(2)=D(1)·A=A^2
            …
        D(n-1)=D(n-2)·A=A^(n-1)
    产生 D(n-1)=(δ(i,j))。
    时间=Θ(n·n3)=Θ(n4)。 不比n×B-F(bellman-ford)好。 

矩阵乘法优化:
重复平方: A^2k=A^k*A^k 

注意: A^n-1=A^n=A^n+1=….
   Time=Θ(n^3*lgn)

即如下形式:
在这里插入图片描述

Floyd-Warshall algorithm(也是dp的一种,但比上述方法快一些)

定义: 从 i 到 j 的最短路径的 cij(k) 权重,中间顶点属于集合 {1,2,…,k}
因此: δ(i,j)=cij (n), cij (0)=aij .
且cij(k)=mink{cij(k-1),cik(k-1)+ckj(k-1)}
示意图:
在这里插入图片描述
求解步骤:

  1. 初始化图的邻接矩阵
  2. 依次以每个顶点作为中间结点,更新邻接矩阵(注意:每次迭代都是在上一步迭代的基础之上进行迭代)
    比如有5个结点v1,v2,v3,v4,v5,则首先以v1作为中间结点更新矩阵,然后再以v2作为中间结点再上一步的基础上再次更新邻接矩阵,再以v3作为中间结点…依此类推,当以v5为中间结点更新结束后,整个算法结束。

Floyd-Warshall 算例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
伪代码:
在这里插入图片描述

Johnson’ algorithm (re-weight)

介绍这个算法发之前有必要了解一下重赋权理论
re-weight theory: 给定一个函数 h: V->R,通过 wh(u,v)=w(u,v)+h(u)-h(v) 对每条边 (u,v) ∈E 重新加权。 然后,对于任何两个顶点,它们之间的所有路径都被重新加权相同的数量。
Johnson’ algorithm step:

  1. 给定图G=(V,E),增加一个新的顶点S,使顶点S与图G中的所有顶点都建立连接,设新的图为G’
  2. 对图G‘中顶点S使用Bellman-Ford算法计算单源最短路径,得到结果h[]={h[1],h[2],…,h[V-1]}
  3. 对原图G中的所有边进行"re-weight“,即对每条边(u,v)其新的权值为:w(u,v)=w(u,v)+h[u]-h[v]
  4. 移除新增的顶点S,再对每个顶点运行Dijkstra算法求得每个顶点的到其余顶点的最短路径δ(u,v)
  5. 最后将求得的结果进行复原操作即:δ(u,v)=δh(u,v)-h(u)+h(v)δ(u,v): 表示u,v的最短路径。

伪代码:
在这里插入图片描述

时间复杂度:Time=O(VE+V^2*lgv)

总结

单源最短路径Dijstra(不能有负权值边),Bell-ford(解决负权值边问题,不能有负权值环,能够检测负权值环)
多源最短路径: Floyd-warshall(通用),Johnson(re-weight)

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值