算法(五):图解贝尔曼-福特算法

算法简介贝尔曼-福特算法(Bellman–Ford algorithm )用于计算出起点到各个节点的最短距离,支持存在负权重的情况它的原理是对图进行最多V-1次松弛操作,得到所有可能的最短路径。其优于迪科斯彻算法的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达O(VE)。但算法可以进行若干种优化,提高了效率。Bellman Ford算法每次对所有的边进行松弛,每次松弛...
摘要由CSDN通过智能技术生成

算法简介

贝尔曼-福特算法(Bellman–Ford algorithm )用于计算出起点到各个节点的最短距离,支持存在负权重的情况

  • 它的原理是对图进行最多V-1次松弛操作,得到所有可能的最短路径。其优于迪科斯彻算法的方面是边的权值可以为负数、实现简单,缺点是时间复杂度过高,高达O(VE)。但算法可以进行若干种优化,提高了效率。

  • Bellman Ford算法每次对所有的边进行松弛,每次松弛都会得到一条最短路径,所以总共需要要做的松弛操作是V - 1次。在完成这么多次松弛后如果还是可以松弛的话,那么就意味着,其中包含负环。

  • 相比狄克斯特拉算法(Dijkstra algorithm),其最大优点便是Bellman–Ford支持存在负权重的情况,并且代码实现相对简单。缺点便是时间复杂度较高,达到O(V*E),V代表顶点数,E代表边数。

可用于解决以下问题:

  • 从A出发是否存在到达各个节点的路径(有计算出值当然就可以到达);
  • 从A出发到达各个节点最短路径(时间最少、或者路径最少等)
  • 图中是否存在负环路(权重之和为负数)

其思路为:

  1. 初始化时将起点s到各个顶点v的距离dist(s->v)赋值为∞,dist(s->s)赋值为0

  2. 后续进行最多n-1次遍历操作(n为顶点个数,上标的v输入法打不出来...),对所有的边进行松弛操作,假设:

    所谓的松弛,以边ab为例,若dist(a)代表起点s到达a点所需要花费的总数, dist(b)代表起点s到达b点所需要花费的总数,weight(ab)代表边ab的权重, 若存在:

    (dist(a) +weight(ab)) < dist(b)

    则说明存在到b的更短的路径,s->...->a->b,更新b点的总花费为(dist(a) +weight(ab)),父节点为a

  3. 遍历都结束后,若再进行一次遍历,还能得到s到某些节点更短的路径的话,则说明存在负环路

思路上与狄克斯特拉算法(Dijkstra algorithm)最大的不同是每次都是从源点s重新出发进行"松弛"更新操作,而Dijkstra则是从源点出发向外扩逐个处理相邻的节点,不会去重复处理节点,这边也可以看出Dijkstra效率相对更高点。

案例

案例一

先举个网上常见的例子介绍其实现的思路:

如下图按Bellman–Ford算法思路获取起点A到终点的最短路径

由上介绍可知,由于该图顶点总数n=5个顶点,所以需要进行5-1 = 4 次的遍历更新操作,每次操作若能发现更短的路径则更新对应节点的值

1.首先建立边对象信息,需要按从源点A出发,由近到远的顺序,不然没从源点开始的话dist(s)==∞无穷大会增加后续计算的麻烦:

AB:-1
AC:4
BC:3
BE:2
BD:2
ED:-3
DC:5
DB:1
复制代码

1.首先列出起点A到各个节点耗费的时间:

父节点 节点 初始化
A A 0
.. B
.. C
.. D
.. E

2.进行第一次对所有边进行的松弛操作:

2.1统计经过1条边所能到达的节点的值AB,AC:

AB:-1
AC:4
复制代码
父节点 节点 耗费
A A 0
A B -1
A C 4
.. D
.. E

2.2统计经过2条边所能到达的节点的值BC,BD,BE:

BC:3
BE:2
BD:2
复制代码
  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值