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

摘要:

1,约翰逊算法的介绍

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

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

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

1,约翰逊算法的介绍

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

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

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

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

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

在上图中从顶点 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 ,如下图所示:

然后我们使用《贝尔曼-福特算法(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)'重新赋值之后的权值。

相关推荐
生成论实验室2 分钟前
《事件关系阴阳博弈动力学:识势应势之道》第二篇:阴阳博弈——认知的动力学基础
数据结构·人工智能·科技·神经网络·算法
li16709027013 分钟前
第二十七章:智能指针
c语言·数据结构·c++·visual studio
风筝在晴天搁浅31 分钟前
字节高频题 小于n的最大数
算法
LabVIEW开发33 分钟前
LabVIEW水力机组空蚀在线监测
算法·labview·labview知识·labview功能·labview程序
AI科技星39 分钟前
科幻艺术书本封面:《全域数学》第一部·数术本源 第三卷 代数原本(P95-141)完整五级目录【乖乖数学】
算法·机器学习·数学建模·数据挖掘·量子计算
风筝在晴天搁浅41 分钟前
LeetCode 92.反转链表Ⅱ
算法·leetcode·链表
王老师青少年编程1 小时前
csp信奥赛C++高频考点专项训练之贪心算法 --【贪心与二分判定】:数列分段 Section II
c++·算法·贪心·csp·信奥赛·二分判定·数列分段 section ii
V搜xhliang02461 小时前
OpenClaw科研全场景用法:从文献到实验室的完整自动化方案
运维·开发语言·人工智能·python·算法·microsoft·自动化
汉克老师2 小时前
GESP2025年3月认证C++五级( 第三部分编程题(2、原根判断))
c++·算法·模运算·gesp5级·gesp五级·原根·分解质因数
数据皮皮侠2 小时前
上市公司创新韧性数据(2000-2024)|顶刊同款 EIR 指数
大数据·人工智能·算法·智慧城市·制造