《经典图论算法》约翰逊算法(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 到其它所有顶点的最短距离disn。

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

相关推荐
ZhengEnCi2 小时前
模型训练完整流程:从数据准备到模型上线的 10 个关键步骤(全文可跑)
后端·算法
吞下星星的少年·-·5 小时前
Div.3 CF 1131A题(排序,模拟)
算法·模拟·排序
aichitang20246 小时前
代数拓扑学与现代前沿视角
考研·算法·数学建模·ai·拓扑学·高考
二本咕咕-机械转码6 小时前
FreeRTOS深入解析(一)_链表与并发保护——哨兵循环链表、排序键游标、临界区与关调度
单片机·算法·链表
-银雾鸢尾-6 小时前
两数之和-C++实现
c++·算法
j7~6 小时前
【动态规划算法专题】动态规划五部曲实战:泰波那契数、三步问题、最小花费爬楼梯
c++·算法·动态规划·数据结构与算法
倍利福猎头公司官方账号6 小时前
大企业HR如何向猎头公司清晰传达AI岗位的技术需求?
人工智能·算法·机器人·求职招聘·业界资讯
揽星河..7 小时前
【C++】类和对象
c++·算法
D e re k ZH7 小时前
C++ 并发、未定义行为与工程化难点(No 3)
数据结构·c++·算法·面试