【算法笔记】多源最短路问题——Floyd算法

Floyd算法(多源最短路) 简介 Floyd算法是一个经典的动态规划算法,它又被称为插点法。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。Floyd算法是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法,算法目标是寻找从点i到点j的最短路径。 实现原理 从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,算法假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,算法检查Dis(i,k) + Dis(k 阅读详情

0. 前言

在图中,如果要求任意两点间的距离,则可以使用Floyd( O ( N 3 ) \mathcal O(N^3) O(N3)😉)和Dijkstra( O ( N M log ⁡ M ) \mathcal O(NM\log M) O(NMlogM)😃)。对于比较小的数据范围(一般为顶点数 N ≤ 150 N\le 150 N≤150),可以使用Floyd算法。本文将讲述Floyd算法的原理、实现和扩展应用。

如果有哪里写得不好请各位dalao多多指教,谢谢!

1. 原理

不同于Dijkstra,Floyd算法同样适用于带负边权的最短路问题。其原理为:
令 f ( x , y ) f(x,y) f(x,y)为从顶点 x x x到 y y y的最短路径。初始时,有:
f ( x , y ) = { 0 ( x = y ) G [ x ] [ y ] ( G [ x ] [ y ] ≠ 0 ) + ∞ ( x ≠ y , G [ x ] [ y ] = 0 ) f(x,y)= \begin{cases} 0 & (x=y) \\ G[x][y] & (G[x][y]\ne0)\\ +\infin & (x\ne y,G[x][y]=0) \end{cases} f(x,y)=⎩ ⎨ ⎧​0G[x][y]+∞​(x=y)(G[x][y]=0)(x=y,G[x][y]=0)​
其中 G G G为图的邻接矩阵, G [ x ] [ y ] G[x][y] G[x][y]表示顶点 x x x到 y y y的边权, 0 0 0表示 x x x到 y y y没有连边。
接下来,考虑枚举中间点 k k k,按 x → k → y x\to k\to y x→k→y的路线计算最短路,则伪代码为:

for k = 1, 2, ..., n
	for x = 1, 2, ..., n
		for y = 1, 2, ..., n
			f[x][y] = min(f[x][y], f[x][k] + f[k][y])

此时,算法结束,最终 f ( x , y ) f(x,y) f(x,y)即为从 x x x到 y y y的最短路。

注意:当给定图为无向图时,对于任意 ( x , y ) (x,y) (x,y), G [ x ] [ y ] = G [ y ] [ x ] G[x][y]=G[y][x] G[x][y]=G[y][x],则 f ( x , y ) = f ( y , x ) f(x,y)=f(y,x) f(x,y)=f(y,x),可改变计算过程(如变成f[k][x]+f[k][y]);但若是有向图,请务必按照伪代码中的顺序编写程序!

2. 代码

Floyd算法的代码可在洛谷 B3647提交。下面给出这题对应的AC代码(注意是按边输入):

#include <cstdio>
#include <cstring>
#define maxn 100
using namespace std;

int dis[maxn][maxn];

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	// 初始化,注意初始值不能超过INT_MAX/2(防止两个INF相加溢出)
	memset(dis, 0x3f, sizeof dis); 
	// 每个点到自己的距离为0
	for(int i=0; i<n; i++)
		dis[i][i] = 0;
	// 读入边
	while(m--)
	{
		int u, v, d;
		scanf("%d%d%d", &u, &v, &d);
		u --, v --; // 0-index
		dis[u][v] = dis[v][u] = d; // 注意两个值都要设
	}
	// Floyd 算法流程
	for(int k=0; k<n; k++) // 中间点
		for(int i=0; i<n; i++) // 起始点
			for(int j=0; j<n; j++) // 终点
			{
				int d = dis[i][k] + dis[k][j]; // i->k->j
				if(d < dis[i][j]) dis[i][j] = d; // 取最短长度
			}
	for(int i=0; i<n; i++, putchar('\n'))
		for(int j=0; j<n; j++)
			printf("%d ", dis[i][j]);
	return 0;
}

3. 扩展

下面问题来了:如何输出结果路径?其实方法很简单。与Dijkstra类似但略有不同,设 path ( x , y ) = x → y \text{path}(x, y)=x\to y path(x,y)=x→y的最短路径上的某一点,则状态转移时若 f ( x , k ) + f ( k , y ) < f ( x , y ) f(x,k)+f(k,y)<f(x,y) f(x,k)+f(k,y)<f(x,y),则不仅要更新 f ( x , y ) f(x,y) f(x,y),还要更新 path ( x , y ) : = k \text{path}(x,y):=k path(x,y):=k。最后,递归输出结果即可。

题面

给定一张有 N N N个点, M M M条边的简单无向图,对于每一对 ( i , j ) (i,j) (i,j)( 1 ≤ i < j ≤ N 1\le i<j\le N 1≤i<j≤N),求 i → j i\to j i→j的最短路径上的每一点。

样例

输入:

5 6
3 4 3
4 1 1
4 5 4
1 2 2
5 2 10
3 2 7

输入图片

输出:

1->2: 1 2
1->3: 1 4 3
1->4: 1 4
1->5: 1 4 5
2->3: 2 1 4 3
2->4: 2 1 4
2->5: 2 1 4 5
3->4: 3 4
3->5: 3 4 5
4->5: 4 5

代码

#include <cstdio>
#include <cstring>
#define maxn 100
using namespace std;

int dis[maxn][maxn], path[maxn][maxn];
void print(int x, int y) // 递归输出x->y的路径,不包含y
{
	int k = path[x][y]; // x->k->y
	if(k == x || k == y) // 两点相邻,直接输出
		printf(" %d", x);
	else
	{
		// 分成两部分递归
		print(x, k); // x->k
		print(k, y); // k->y
	}
}

int main()
{
	int n, m;
	scanf("%d%d", &n, &m);
	// 初始化
	memset(dis, 0x3f, sizeof dis); 
	for(int i=0; i<n; i++)
		dis[i][i] = 0;
	// 读入边
	while(m--)
	{
		int u, v, d;
		scanf("%d%d%d", &u, &v, &d);
		dis[u][v] = dis[v][u] = d; // 注意两个值都要设
		path[u][v] = path[v][u] = u; // 初始化path
	}
	// Floyd 算法流程,为了方便输出,采用1-index
	for(int k=1; k<=n; k++) // 中间点
		for(int i=1; i<=n; i++) // 起始点
			for(int j=1; j<=n; j++) // 终点
			{
				int d = dis[i][k] + dis[k][j]; // i->k->j
				if(d < dis[i][j]) // 更新最短路径
					dis[i][j] = d, path[i][j] = k;
			}
	// 依次枚举(i,j) 输出路径
	for(int i=1; i<n; i++)
		for(int j=i+1; j<=n; j++)
		{
			printf("%d->%d:", i, j);
			print(i, j);
			printf(" %d\n", j);
		}
	return 0;
}

注:由于每条路径的长度不会超过 N N N,所以总时间复杂度仍为 O ( N 3 ) \mathcal O(N^3) O(N3)。

4. 后记

总结:Floyd算法时间复杂度为 O ( N 3 ) \mathcal O(N^3) O(N3),写起来很方便。如果觉得好就请给个三连,谢谢支持!

C++算法:多源最短路径(Floyd) 前文单源最短路径Dijkstra中我们讨论了如何解决有向无环图的最短路径问题,Dijkstra只能解决一个起始点的问题,如果要解决每个顶点到任一顶点的最短路径呢?一个方法就是再循环一次,以每个顶点作为起点就可以了嘛,虽然不可避免的会有部分重复工作,但确实能解决,就是代码更复杂了。有没有一个优雅点的办法呢?今天要介绍的算法Floyd(弗洛伊德,好熟悉的名字~)就是一个优雅的解决办法。它与用Dijkstra循环每个顶点的时间复杂度差不多O(n3),但是代码极简。 阅读详情

相关推荐

数据结构------最短路弗洛伊德算法(Flody)

Foldy算法动态规划,详解代码,优缺分析!

m0_62749134的博客 1743

多源最短路——Floyd算法

多源最短路 Floyd算法

weixin_44229144的博客 464

Floyd 算法--多源最短路

我们是把 k =0 的 i 和j 对应的数值都初始化了,这样才能去计算 k = 1 的时候 i 和 j 对应的数值。grid[i][j][k] = m,表示 节点i 到 节点j 以[1...k] 集合为中间节点的最短距离为m。你可以反过来想,节点i 到 节点j 中间一定经过很多节点,那么你能用什么方式来表述中间这么多节点呢?节点i 到 节点k 的最短距离 不经过节点k,中间节点集合为[1...k-1],所以 表示为。,同理节点k 到 节点j 的最短距离 也是不经过节点k,表示为。节点i 到 节点j 的。

qq_73704268的博客 823

图详解第六篇:多源最短路径--弗洛伊德(Floyd-Warshall)算法(完结篇)

多源最短路径--Floyd-Warshall算法

m0_70980326的博客 1万+

编程_三大编程思想:POP、OOP、AOP

简单介绍POP、OOP、AOP三大编程思想的区别和优缺点~

mikimo的博客 3898

MySQL8.2.0下载安装

4、点击No thanks,just start my download,就是只是开始下载的意思,点击下载,等待下载完成。5、新建空白行,或直接双击紧挨的空白行,把复制的mysql的安装路径bin路径复制粘贴过来,确定,确定,确定。1、上面点击finish后,自动勾选了run mysql配置,自动会打开配置页面,点击Next。1、双击安装包,进入安装流程,勾选我同意 I accept,next。2、根据自己需要选择,我选的第二个,可以自己改安装路径。2、默认,点击Next,记住默认端口3306。

m0_59681797的博客 1万+

【数据结构笔记24】单源最短路(迪克斯拉Dijkstra算法),多源最短路(弗洛伊德Floyd算法)

有权图的单源最短路使用的Dijkstra算法,多源最短路算法使用的Floyd算法。

记录学习痕迹的公众号:Piper蛋窝 1558

使用CLion在Window端进行linux开发

        以往不管是开发x86端linux程序还是arm端linux程序,都是使用Source Insight作为源码编辑工具的,如下图      去年底,发现CLion的2018.3更新版本,可以支持remote host开发了,大爱!     我是基于以下几点原因,将开发工具换成CLion 1. 语法高亮较明显、跳转、重构方便(我很看重这个); 2. 可以使用图形界面进行调...

alist的笔记专栏 1万+

图论最短路总结Dijkstra&Floyd

以下是我对Dijkstra算法:求解单源最短路问题以及Floyd算法:求解多源最短路问题的笔记总结。希望能对大家理解这两个算法有帮助。

m0_75259338的博客 262

解决 `version ‘GLIBCXX_3.4.32‘ not found‘ not found` 错误

解决 `version 'GLIBCXX_3.4.32' not found' not found` 错误

engchina的专栏 5677

一文读懂 SAP BTP Application Router 的 Resource Files:从 xs-app.json 到本地开发的默认设置

本文详解SAP BTP中Application Router的资源文件配置与本地开发实践。核心包括:xs-app.json定义路由规则与安全策略,package.json声明依赖与启动脚本,resources/存放静态资源,default-services.json和local-destinations.json用于本地模拟云服务。文章通过真实案例展示如何配置静态资源直出、反向代理后端服务,并强调本地开发时的注意事项与常见问题解决路径。关键配置均提供示例代码,帮助开发者快速实现业务应用的部署与联调。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 180

图论最短路学习笔记(二)Floyd算法详解:阈值距离内邻居最少的城市

Floyd算法详解:阈值距离内邻居最少的城市

学习记录 875

基于FPGA的NCO实现

NCO实现原理 数字振荡器 输出频率,相位可控的正弦波,精度高,稳定性高,替代VCO,用起来方便也易于操作。 实现方式: 直接调用fpga里面的ip核,以下是IP核的配置方法: 接下来选择输出为单路还是多路: 最后生成ip核时需要注意的事项: 生成时会需要漫长的等待,因此需要如下操作: 最后成功生成: 实现代码: input clk ; input rst_n ; output [13:0]fsin_i ; wire [13:.

m0_46644103的博客 4581

最短路问题——多源最短路

当处理到第。

2301_80224556的博客 1579

HanLP的分词

HanLP的分词

sikh_0529的博客 1万+

【Halcon-2D测量】add_metrology_object_rectangle2_measure 函数功能(用于向2D计量模型中添加旋转矩形(rectangle2类型)计量对象)

HALCON算子add_metrology_object_rectangle2_measure解析摘要 该算子是HALCON 2D计量模块的核心算子,用于添加旋转矩形计量对象并配置测量参数。主要功能包括:定义旋转矩形几何轮廓(中心坐标、主轴角度、长短半长);生成垂直于矩形边界的测量区域;设置边缘提取预处理参数(高斯平滑、振幅阈值)。关键注意事项:MeasureLength1必须小于矩形长短半长;角度参数Phi需使用弧度单位;多线程需同步模型句柄。该算子适用于方形螺母、PCB板边框等矩形零件的精密测量,需与a

weixin_45590420的博客 1225

【洛谷】图论 图论最短路算法全解:从单源 Dijkstra 到多源 Floyd 模板与实战

本文系统梳理图论中两类核心最短路问题:单源最短路与多源最短路。详细讲解基于贪心思想的 Dijkstra 算法(含常规版与堆优化版),以及基于动态规划的 Floyd 插点法,包含算法原理、状态转移、代码实现与边界处理,并提供竞赛模板,帮助读者快速掌握最短路问题的求解思路与工程实现。

2501_90265152的博客 1422

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

多源最短路的两种做法和详细解析

多源最短路的分析和讲解,讲解 Floyd 算法的原理和代码实现。

peterJr的博客 2271

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

多源最短路算法——Floyd算法

1.多源最短路简介: 我们知道单源最短路是指从某一个源点到图中的其它顶点的最短路。 多源最短路就是指每一个点到图中其他顶点的最短路。 那么有的人肯定想我知道求单源最短路的算法了,那么有多少个点我就求多少次呗,这样做时间效率不高,空间效率也极其低。 那么有什么算法求解多源最短路呢?——Floyd 2.Floyd简介: 3.三维空间Floyd核心代码: int g[N][N]; // 邻接矩阵存图...

ly's Blog 3242

图论 24. Floyd算法(多源最短路问题)

​。

m0_49844155的博客 1281

【图论——第六讲】Floyd算法求多源最短路问题

算法图论题中关于求多源最短路问题的Flody算法

m0_63233163的博客 1292

多源最短路:Floyd算法の暴力美学

这里我们求环的长度的时候加了三次,是有可能溢出的,根据C++的语法规则,溢出后变成负数,此时结果就被更新成负数,题目中m的范围是5×103,其实我们可以把INF定义为1e8就可以。5. 初始化:由于我们要做min操作,所以开始时要把所有的状态初始化成INF,从i 到 i 的最短路是零,所有还要把 f[i][i] 初始化成零(i从1 到 n)。题目要求A1 A2 A3 --- An,让我们求最小的危险指数,从任意一点到另一点可以经过别的点,所以本题求得任意两点之间的最小危险指数,其实就是求最短路之和。

2403_87718362的博客 762

短小精悍的多源最短路径算法—Floyd算法

目录前言算法介绍 前言 在图论中,在寻路最短路径中除了Dijkstra算法以外,还有Floyd算法也是非常经典,然而两种算法还是有区别的。 在单源正权值最短路径,我们会用Dijkstra算法来求最短路径,并且算法的思想很简单——贪心算法:每次确定最短路径的一个点然后维护(更新)这个点周围点的距离加入预选队列,等待下一次的抛出确定。但是虽然思想很简单,实现起来是非常复杂的,我们需要邻接矩阵(表)储存...

bigsai 7518

【算法】图论——单源最短路问题

邻接矩阵存储图判断一个顶点是否已经确定最短路的数组从起点到第i个点的距离数组。距离数组中可能暂时存储的不是最短路,具体看上面的判断数组题目链接:邻接表边的权值表距离表判断表,用于判断该顶点是否遍历过堆,使用STL中的priority_queueedges[M]:用于存储所有边,M为边的数量dis[N]:用于存储经过一次松弛操作后的顶点距离backup[N]:dis的拷贝为什么要有backup?

m0_73904148的博客 1935

【算法】Floyd多源最短路径算法

算法学习笔记之Floyd多源最短路径算法

Eristic0618的博客 1301

图论 最短路(2)多源最短路

Floyd算法是一种经典的多源最短路算法,通过动态规划思想求解图中任意两点间的最短路径,时间复杂度为O(n³)。该算法使用邻接矩阵存储图结构,通过三重循环实现状态转移。文章详细介绍了Floyd算法的原理、实现模板及其应用场景,包括负权环检测、最小环求解和传递闭包问题。此外,还介绍了Johnson算法作为处理负权图的替代方案,通过建立超级源点和重赋权值将负权图转化为正权图,再利用Dijkstra算法求解。两种算法各有适用场景,Floyd适合稠密图,Johnson则更适合处理含负权的稀疏图。

2501_92685363的博客 1510
上一篇: 【算法笔记】树形DP算法总结&详解
下一篇: 【算法笔记】单源最短路问题——Dijkstra算法(无优化/优先队列/set优化)
GoodCoder666
博客等级 码龄7年 2320粉丝 85原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值