单源点最短路径算法:Bellman-Ford算法

背景知识

图简介

图由节点和边组成,边有方向的图称为有向图,边没有方向的图称为无向图,最短路径算法里可以把无向图视为双向连接的有向图。
边有权重的图称为有权图,边没有权重的图称为无权图,无权图可以视为边的权重均为1的图。

单源点最短路径

给定图中的一个节点,求该节点到其他所有节点的最短路径。

Bellman-Ford算法

概述

Bellman-Ford属于DP算法,适用于含负权边的图,并且可以检测图中是否含有负权环(意味着没有最短路径),时间复杂度为O(VE)

核心思想

对所有边进行V-1次遍历,第一次遍历获得边数为1的最短路径,第二次遍历获得边数为2的最短路径,以此类推,第V-1次遍历获得边数为V-1的最短路径。V-1次遍历后,进行第V次遍历,如果能够获得更小的路径长度,说明存在负环。

算法步骤

dis[]用于存储每个节点到源点src的距离,preNode[]存储每个节点的前驱节点
Step1:初始化dis[]为INT_MAX,dis[src]初始化为0. preNode[src]初始化为-1.
Step2:遍历图中的每条边edge(v,u),若dis[v]不为INT_MAX,且dis[v] + weight(v,u) < dis[u],执行dis[u] = dis[v] + weight(v,u)。
Step3:重复Step2 V次,若某次遍历没有执行dis[u] = dis[v] + weight(v,u),即发生了松弛,结束Step3
Step4:判断Step3最后一次执行是否发生松弛,若发生,说明图中含有负权环,若没有发生,说明图中没有负权环。

为什么能获得最短路径

可以从直观上理解,第一次遍历获得了(距离源点)边数量为1的最短路径,第二次在第一次的基础上获得了边数量为2的最短路径,第三次在第二次的基础上获得了边数量为3的最短路径,依次类推,有些节点到源点有很多条路径,这些路径的边数可能不一样也可能一样,算法会在V-1循环中比较这些路径的长度,取最小值作为最短路径(遍历中边数多的可能距离可能反而小于边数少的,这个时候就会发生松弛了)。

为什么最后一次遍历是否发生松弛可以判断负环

有两种情况会导致Step3结束,一是当次遍历没有发生松弛,二是已经循环了V次,情况一显然不存在负环,不然肯定可以继续松弛。情况二下,如果最后一次遍历发生了松弛,说明第V次松弛了,意味着找到的边长数为V的最短路径,而最长的最短路劲应该是V-1条边, 所以肯定至少一条边重复了,一定是出现环了,环路径比非环更短,说明是负环。
举个最简单的例子:
这里写图片描述
第一次遍历 dis[1] = 2, dis[2] =INT_MAX
第二次遍历 dis[1] = 2, dis[2] = 3;
已经遍历了V-1即两次了,第3次遍历,dis[1] = dis[2] + wegiht(2,1) = 1,小于dis[1],所以会继续发生松弛。
如果weight(1,2) = 3,环长度为3-2=1,正环,这个时候第V次遍历就不会发生松弛了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值