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

Floyd-Warshall——仅用4行代码就能解决多源最短路径问题的算法

文章目录

  • 前言
  • Floyd思路
  • 示例
  • 总结

前言

Floyd-Warshall算法简记Floyd算法,又称弗洛伊德算法,是解决任意两点间的最短路径问题的一种常用算法,核心思想就是“不断利用第三者影响原配关系”,这一点在4行核心代码中表现的淋漓尽致,接下来梳理一下算法思路。

Floyd思路

从A点走到B点要想路径最短只有两种可能,一种就是直接从A到B,另一种就是通过其他点来中转,Floyd的思路就是先把直接能到达的点固定下来,然后不断的尝试从其他点来中转来降低路程。

Floyd算法实现通常使用一个二维数组来表示任意两点之间的初始距离,每个点到自身的距离为0,若两个点之间没有直接连通,则赋值为 +∞,我们假设这个二维数组是 v,则 v[i][j] 代表了从点 i 到点 j 的初始距离。

假设不允许中转,那么二维数组 v 中的数据就代表了任意两点间的距离。

如果允许中转一次,我们假设只允许从节点1进行中转,那么点 i 到点 j 的最近距离最小为 v[i][j] 或者 v[i][1] + v[1][j],如果 v[i][1] + v[1][j] 的值更小,我们可以使用它来更新 v[i][j] 的值,这时 v[i][j] 就不仅仅是一个值了,而是隐含着 i->1->j 这样一条路径,这个过程实际上翻译成代码就是:

for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)
        v[i][j] = min(v[i][j], v[i][1] + v[1][j]);

那么这条路径怎样才能更短呢?

答案就是引入另一个点,比如我们不仅允许从节点1中转,也允许从节点2中转,从上一步我们知道从从点 i 到点 j 的最短距离是从 i->1->j 得到的,实际上经过上面一步,任意两点的距离都是允许从节点1中转条件下的最小值, 那么引入节点2之后就是要看看 v[i][j]v[i][2] + v[2][j] 谁更小一点,然后遍历更新即可,类似的代码可以写成:

for(int i = 0; i < n; i++)
    for(int j = 0; j < n; j++)
        v[i][j] = min(v[i][j], v[i][2] + v[2][j]);

看到套路了没有,就是每个点都作为一个可能中转的点来试一下,整个算法就结束了,好神奇~ 完整4行代码如下:

for(int k = 0; k < n; k++)
    for(int i = 0; i < n; i++)
        for(int j = 0; j < n; j++)
            v[i][j] = min(v[i][j], v[i][k] + v[k][j]);

简单粗暴又不失美感!

示例

初始路径及每条边的距离如图:

路径

  1. 翻译成二维数组如下:
0274
04
910
6150
  1. 仅通过节点0作为中转,二维数组更新如下:
0274
04
91013
68130
  1. 增加节点1作为中转,二维数组更新如下:
0264
04
91013
68120
  1. 再增加节点2作为中转,二维数组更新如下:
0264
130417
91013
68120
  1. 最后增加节点3作为中转,二维数组更新如下:
0264
130417
91013
68120

至此我们就求解出了任意两点间的最小距离。

总结

  • Floyd算法的时间复杂度为O(N^3),空间复杂度为 O(N^2)
  • Floyd是一种求解多源最短路径的算法,如果是求解单源最短路径这 N^3 的时间复杂度确实有点伤
  • Floyd可以正确处理有向图或存在负权边的图,但不能处理存在负权回路的图的最短路径问题
  • 4行代码3层循环或许可以助它称为最容易让人理解的最短路径算法
  • 这4行代码只是一个理想化的模型,实际在编码时要注意加法的越界问题,因为两个无穷大相加理论上是无穷大,但在代码里可能就崩溃了

==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

人生到底是追求到达目的地还是准备欣赏沿途的风景,一味地向前奔跑忽略了周围的一切,很多美好的事物就在身边却不自知,我们已经被世俗蒙蔽了双眼,什么时候可以慢下来呢?

相关文章:

  • Dijkstra——通过不断松弛来解决单源最短路径问题的算法
  • C++11中的std::atomic保证的原子性是什么
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • linux环境下从路径字符串中截取目录和文件名信息
  • MD5是用来加密的吗?BCrypt又是什么呢
  • 树的带权路径长度和哈夫曼树
  • 完全图与强连通图的那些坑
  • linux环境下恢复rm误删的文件
  • 记一次使用Valgrind查找解决内存问题的玄幻旅程
  • 网络工具nc的常见功能和用法
  • git常用配置——git show/diff tab 显示宽度
  • Windows设置防火墙允许指定应用正常使用网络
  • 2021年终总结——脚踏实地,为下一次腾飞积蓄力量
  • 通过WindowsStore安装QuickLook小工具方便文件预览
  • linux环境下随时照看服务器进程的ps和top命令
  • 【知识碎片】第三方登录弹窗效果
  • cookie和session
  • input的行数自动增减
  • JavaScript 基本功--面试宝典
  • markdown编辑器简评
  • PHP 的 SAPI 是个什么东西
  • PV统计优化设计
  • Vultr 教程目录
  • 动态魔术使用DBMS_SQL
  • 工作手记之html2canvas使用概述
  • 观察者模式实现非直接耦合
  • 聚类分析——Kmeans
  • 跨域
  • 排序(1):冒泡排序
  • 王永庆:技术创新改变教育未来
  • 我的zsh配置, 2019最新方案
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • 整理一些计算机基础知识!
  • #微信小程序:微信小程序常见的配置传旨
  • $.ajax()参数及用法
  • (20)目标检测算法之YOLOv5计算预选框、详解anchor计算
  • (20050108)又读《平凡的世界》
  • (9)目标检测_SSD的原理
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (安全基本功)磁盘MBR,分区表,活动分区,引导扇区。。。详解与区别
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)ssm航空客运订票系统 毕业设计 141612
  • (接口自动化)Python3操作MySQL数据库
  • (一) storm的集群安装与配置
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • (原創) 未来三学期想要修的课 (日記)
  • (转)创业的注意事项
  • (转载)Google Chrome调试JS
  • (转载)深入super,看Python如何解决钻石继承难题
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .Net 8.0 新的变化
  • .net mvc部分视图
  • .NET Standard、.NET Framework 、.NET Core三者的关系与区别?
  • .net6Api后台+uniapp导出Excel