惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
小众软件
小众软件
博客园 - 叶小钗
宝玉的分享
宝玉的分享
博客园_首页
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
S
SegmentFault 最新的问题
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
N
Netflix TechBlog - Medium
Google DeepMind News
Google DeepMind News
U
Unit 42
F
Fortinet All Blogs
IT之家
IT之家
Y
Y Combinator Blog
Martin Fowler
Martin Fowler
T
The Blog of Author Tim Ferriss
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The GitHub Blog
The GitHub Blog
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell

又见苍岚

COLMAP PatchMatch Stereo 算法详解 事件驱动的状态机框架:从理论到工程实践 Git 在国内网络环境下无法 Push 的排查与修复 —— 配置 Clash 代理 分段五次多项式插值原理详解 路径插值方法深度对比研究 Claude Code 使用指南 OpenClaw 记忆管理与技能创建指南 CBS(Conflict-Based Search)算法详解 A* 算法及其变种详解 OpenClaw 配置多 Agents Windows Powershell 无法加载文件,因为在此系统上禁止运行脚本问题的解决方案 MaxClaw 安装流程 大模型 AI 名词介绍 AList 网盘聚合工具简介 Protobuf 简介与测试 Claude Code 简介以及 GLM 4.7 模型接入 Github 歌词下载工具 163MusicLyrics Python __getattr__ 懒加载 Python TypedDict 机器人仿真平台 Gazebo 安装记录 机器人仿真平台 Gazebo 简介 多机器人路径规划问题(Multi-Agent Path Finding, MAPF)简介 Python exifread 读取修改过的 jpeg 信息错误问题修复 3D 坐标系变换的理解 3D 旋转矩阵基本概念 MongoDB Compass 介绍 Python 环境管理工具 uv Flutter 开发指南 Snipaste 安装下载与黑屏问题解决方案 全局路径规划算法记录
Floyd算法——求图中所有点之间最短路径
Yiwei Zhang · 2024-08-05 · via 又见苍岚

本文记录可以找到图中所有点之间最短路径的经典算法 —— Floyd 算法。

简介

Floyd 算法又称为插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,与Dijkstra算法类似。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。简单的来说,算法的主要思想是动态规划(dp),而求最短路径需要不断松弛。

根据目前已知的任意两点间的最短路径,依次以各个节点作为中间节点改变路径,不断比较寻找任意两点间更短的路径,直到所有节点都作为过中间节点后,得出最短路径。

算法思想

  1. 邻接矩阵(二维数组)dist储存路径,数组中的值开始表示点点之间初始直接路径,最终是点点之间的最小路径,有两点需要注意的,第一是如果没有直接相连的两点那么默认为一个很大的值(不要因为计算溢出成负数),第二是自己和自己的距离要为0。

  2. 从第1个到第n个点依次加入松弛计算,每个点加入进行试探枚举是否有路径长度被更改(自己能否更新路径)。顺序加入(k枚举)松弛的点时候,需要遍历图中每一个点对(i,j双重循环),判断每一个点对距离是否因为加入的点而发生最小距离变化,如果发生改变(变小),那么两点(i,j)距离就更改。

    状态转移方程为:

    1
    dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])

    其中dp[a][b]的意思可以理解为点a到点b的最短路径,所以dp[i][k]的意思可以理解为i到k的最短路径dp[k][j]的意思为k到j的最短路径.

  3. 重复上述直到最后插点试探完成。

算法图解

初始情况每个点只知道和自己直接相连的点的距离,而其他间接相连的点还不知道距离,比如 A-B=2, A-C=3 但是 B-C 在不经过计算的情况是不知道长度的。

加入第一个节点A进行更新计算,大家可以发现,由于 A 的加入,使得本来不连通的B,C点对和B,D点对变得联通,并且加入 A距离为当前最小,同时你可以发现加入A其中也使得C-D多一条联通路径(6+3),但是C-D联通的话距离为9远远大于本来的(C,D)联通路径2,所以这条不进行更新。

继续加入第二个节点B,这个点执行和前面A相同操作进行。对一些点进行更新。因为和 B 相连的点比较多,可以产生很多新的路径。

这里新路径统一用1表示,原来长度用0表示。

AF1=AB+BF=6+2=8 < AF0(∞) 进行更新

AE1=AB+BE=2+4=6 < AE0(∞) 进行更新

CE1=CB+BE=5+5=9 < CE0(∞) 进行更新

CF1=CB+BF=5+6=11<CF0(∞) 进行更新

EF1=EB+BF=4+6=10<EF0(∞) 进行更新

当然,也有一些新的路径大于已有路径不进行更新,例如:

AC1=AB+BC=2+5=7>AC0(3) 不更新

AD1=AB+BD=2+8=10>AD0(6) 不更新

……

后序加入C、D、E、F都是进行相同的操作,最终全部加完没有路径可以更新就结束停止。实际上这个时候图中的连线就比较多了。这些连线都是代表当前的最短路径。 这也和我们的需求贴合,我们最终要的是所有节点的最短路径。每个节点最终都应该有5条指向不同节点的边! 矩阵对应边值就是点点之间最短路径。

复杂度

Floyd-Warshall算法的时间复杂度为 ${\displaystyle O(|V|^{3})}$,空间复杂度为 ${\displaystyle O(|V|^{2})}$,其中 ${\displaystyle V}$ 是点集。

参考资料

文章链接:
https://www.zywvvd.com/notes/study/algorithm/graph/floyd/floyd/