当前位置: 首页 > article >正文

《经典图论算法》约翰逊算法(Johnson)

摘要:

1,约翰逊算法的介绍

2,约翰逊算法的实现步骤

3,约翰逊算法的准确性验证

4,约翰逊算法的代码实现

1,约翰逊算法的介绍

约翰逊算法(Johnson algorithm)是在稀疏图上求每对顶点之间最短路径的一种算法,该算法在 1977 年由 Donald B. Johnson 提出。

在前面我们讲过求任意两对顶点之间的最短路径可以使用《Floyd算法》,它可以解决有负权边的图,但不能有负权回路,它的时间复杂度是O(n^3),非常高。

我们知道《迪杰斯特拉算法》是求单源点最短路径的,也就是计算从一个点到其它所有点的最短距离。

而堆优化的迪杰斯特拉算法时间复杂度是O((V+E)logV),如果是稀疏图的话,边的数量 E 就会比较小,我们可以以每一个顶点为起始点跑一遍迪杰斯特拉算法即可求出任意两点之间的最短路径。

但迪杰斯特拉算法有个缺点就是不能有负权边,这个时候我们可能想到的是,给每一条边都加上一个值,让它们都变成正的就好了,但这样也是不行的,如下图所示:

dd407d483b6babe0d0222177583ff48e.png

在上图中从顶点 1 到顶点 3 的最短路径本来是 1→4→5→6→3,长度为 2。如果我们把每条边都加上 4 ,这样边的权值虽然没有负数了,但从顶点 1 到顶点 3 的最短路径也改变了,变成了 1→2→3 ,长度为13,已经不是原来的最短路径了,原来的最短路径 1→4→5→6→3 长度变成了 18 。

这是因为原来的最短路径经过的边数比较多,如果每条边都加同一个值,原来的最短路径累加的值就越大,就可能导致最短路径发生改变。

这个时候我们可以考虑使用Johnson 算法,Johnson 算法就是通过另外一种方式来给每条边重新标注权值。

2,约翰逊算法的实现步骤

Johnson算法的精髓就是预处理,确保所有边的权值均非负。使用Johnson算法我们需要添加一个虚拟节点(这里我们假设它的编号为 0 ),这个虚拟节点指向其它所有的顶点,并且权值都为 0 ,如下图所示:

c8a2448d97cce9763672d77b20a947f4.png

然后我们使用《贝尔曼-福特算法(Bellman-Ford)》或者《SPFA算法》来计算从顶点 0 到其它所有顶点的最短距离dis[n]。

接着再给所有的边重新赋值,将w(u,v)变成w(u,v)' = w(u,v) + dis(u) - dis(v),w(u,v)是原来边<u,v>的权值,w(u,v)'重新赋值之后的权值。


http://www.kler.cn/a/320845.html

相关文章:

  • 【ubuntu18.04】vm虚拟机复制粘贴键不能用-最后无奈换版本
  • Pytest从入门到精通
  • 物理hack
  • Markdown中输入空格的几种不同方式
  • 【Linux:IO多路复用(select、poll函数)
  • 鸿蒙学习生态应用开发能力全景图-开发者支持平台(5)
  • 前端插件开发用什么技术比较好,用来程序自动化下载
  • TypeScript 设计模式之【单例模式】
  • [每日一练]修复表中的名字
  • Dependency Check:一款针对应用程序依赖组件的安全检测工具
  • ACM MM24 | Hi3D: 3D生成领域再突破!新视角生成和高分辨率生成双SOTA(复旦智象等)
  • Java 编码系列:异常处理与自定义异常
  • 一些广泛认可的编程工具,在不同的方面帮助我们提升效率
  • 使用cmd命令窗口操作mongodb
  • Scikit-LearnTensorFlow机器学习实用指南(三):一个完整的机器学习项目【下】
  • mask2former训练自定义数据集
  • Leetcode算法基础篇-位运算
  • 架构师论文备考-论软件系统架构评估
  • 云轴科技ZStack AIOS平台智塔亮相华为全联接大会
  • 在 macOS 上安装 ADB给安卓手机装APK,同样适用智能电视、车机
  • 单词的秘密2
  • DNS协议解析
  • leetcode第十三题:罗马数字转整数
  • win 录屏软件有哪些?5个软件帮助你快速进行电脑录屏。
  • 记录一次学习--委派攻击学习
  • 关于在vue2中自定义右键弹窗