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

news2025/3/29 18:00:25

多源最短路求解的是图中的任意两个节点之间的最短路

前文我们已经讲过单源最短路,我们完全可以做n次单源最短路算法,求出任意两节点的最短距离。最快的堆优化版的 dijkstra 算法的时间复杂度为o(m * logm),枚举n次时间复杂度变为o(n * m * logm)。

但是我们下文介绍的基于动态规划实现的Floyd算法阶段性求解的方法才是多源最短路中最重要的。

Floyd算法

Floyd算法的本质是动态规划,也叫做插点法。通过不断在两点之间插入新的结点来更新最短路。

注意:Floyd算法适用于任何可以求解最短路的图,也就是说不能有负环

1. 状态表示:f[k][i][j] :表示仅仅经过【1 - k】这些结点时,i 到 j的最短路

2. 状态转移方程:分析方法和背包问题相似。

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

3. 空间优化:由于是一层一层的遍历,所以我们可以去除第一维。

4. 填表顺序:填表的时候依赖的是 k - 1层的状态,所以一定要从 k 开始枚举。然后填表的时候正常从左到右,从上到下填。

5. 初始化:由于我们要做min操作,所以开始时要把所有的状态初始化成INF,从i 到 i 的最短路是零,所有还要把 f[i][i] 初始化成零(i从1 到 n)。

6. 最终结果:任意两个i j 就是两点间的最短路了。


B3647 【模板】Floyd - 洛谷

题目来源:洛谷

题目难度:

【解题】:一道模板题啦~

🖥️code:

#include <iostream>
#include <cstring>

using namespace std;
const int N = 110, INF = 0x3f3f3f3f;

int n, m;
int f[N][N]; // dp表,同时也是邻接矩阵的存法

int main()
{
	cin >> n >> m;
	
	// 初始化 
	memset(f, 0x3f, sizeof f);
	for(int i = 1; i <= n; i++) f[i][i] = 0;
	for(int i = 1; i <= m; i++)
	{
		int a, b, c; cin >> a >> b >> c;
		// 无向图存两遍,同时避免重边 
		f[a][b] = f[b][a] = min(f[a][b], c);
	}
	
	// 填表
	for(int k = 1; k <= n; k++)
	{
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= n; j++)
			{
				f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
			}
		}
	} 
	
	// 最后f表就是任意两点的最短路
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			cout << f[i][j] << " ";
		}
		cout << endl;
	} 
	return 0;
}


P2910 [USACO08OPEN] Clear And Present Danger S - 洛谷

题目来源:洛谷

题目难度:

【解题】:题目要求A1 A2 A3 --- An,让我们求最小的危险指数,从任意一点到另一点可以经过别的点,所以本题求得任意两点之间的最小危险指数,其实就是求最短路之和。

#include <iostream>
#include <cstring>

using namespace std;

const int N = 110, M = 1e4 + 10, INF = 0x3f3f3f3f;

int f[N][N];
int a[M];
int n, m;

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= m; i++) cin >> a[i];
	
	// init
//	memset(f, 0x3f, sizeof f);
	for(int i = 1; i <= n; i++) f[i][i] = 0;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			cin >> f[i][j];
		}
	}
	
	for(int k = 1; k <= n; k++)
		for(int i = 1; i <= n; i++)
			for(int j = 1; j <= n; j++)
				f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
	int ans = 0;
	for(int i = 1; i < m; i++) ans += f[a[i]][a[i + 1]];
	cout << ans << endl;
	return 0;
} 


P1119 灾后重建 - 洛谷

题目来源:洛谷

题目难度:★★

【解题】:本题利用了Floyd算法阶段性解决最短路的特点。本题最关键的地方是村庄修复时间不下降和Q次询问的时候给的时间不下降,使我们可以阶段性插入节点。

当该村庄未修复完成时,它的道路不可走,我们就不插入这个节点,反之就插入这个节点。所以在不断插入的过程中就可以得出改时间的两点最短路。

🖥️code:

#include <iostream>
#include <cstring> 

using namespace std;

const int N = 210, INF = 0x3f3f3f3f;

int n, m;
int t[N];
int f[N][N];

void floyd(int k)
{
	for(int i = 0; i < n; i++)
		for(int j = 0; j < n; j++)
			f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
}

int main()
{
	cin >> n >> m;
	for(int i = 0; i < n; i++) cin >> t[i];
	memset(f, 0x3f, sizeof f);
	for(int i = 0; i < n; i++) f[i][i] = 0;
	for(int i = 1; i <= m; i++)
	{
		int a, b, c; cin >> a >> b >> c;
		f[a][b] = f[b][a] = c;
	}
	int pos = 0;
	int Q; cin >> Q;
	while(Q--)
	{
		int a, b, c; cin >> a >> b >> c;
		while(pos < n && t[pos] <= c) floyd(pos++);
		
		if(t[a] > c || t[b] > c || f[a][b] == INF) cout << -1 << endl;
		else cout << f[a][b] << endl;
	}	
	return 0;
}

P6175 无向图的最小环问题 - 洛谷

题目来源:洛谷

题目难度:★★

【解题】:其实这一题也是模板题。首先我们需要给这些环分类:按照环中节点编号的最大值分 

类。在Floyd算法插入第k个结点之前,记录着从 1 - k-1 任意一个结点选择,任意两点的最短路。

此时我们强行插入第 k 个结点(注意我们并不关心i - j到底怎么走),就成了最编号为k的环,对这

些环取最小值就可以。

🖥️code:

#include <iostream>
#include <cstring>

using namespace std;

const int N = 110, M = 5e3 + 10, INF = 1e8;

int n, m;
int f[N][N];
int e[N][N];

int main()
{
	cin >> n >> m;
	for(int i = 1; i <= n; i++)
	{
		for(int j = 1; j <= n; j++)
		{
			f[i][j] = e[i][j] = INF;
		}
	}
	for(int i = 1;  i<= n; i++) f[i][i] = 0;
	for(int i = 1; i <= m; i++)
	{
		int a, b, c; cin >> a >> b >> c;
		f[a][b] = f[b][a] = min(f[a][b], c);
		e[a][b] = e[b][a] = min(e[a][b], c);
	}
	
	// floyd
	int ans = INF; 
	for(int k = 1; k <= n; k++)
	{
		// 此时f表的阶段为从1 - k-1 点中选出从i - j的最短路
		// 将图按照最大结点编号划分,此时将k结点插入,就得到了最大编号为k的最小环
		for(int i = 1; i < k; i++)
		{
			for(int j = i + 1; j < k; j++)
			{
				int t = f[i][j] + e[i][k] + e[k][j];
				ans = min(ans, t);
			}
		 } 
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= n; j++)
			{ 
				f[i][j] = min(f[i][j], f[i][k] + f[k][j]);
			}
		}
	 } 
	if(ans == INF) cout << "No solution." << endl;
	else cout << ans << endl;
	return 0;
}

注意代码中的一个细节:

我么之前一直用0x3f3f3f3f代表无穷大的原因:

1、0x3f3f3f3f 大概是1e9级别的数,很大。

2、0x3f3f3f3f * 2 刚好不会超过 int 的范围。

这里我们求环的长度的时候加了三次,是有可能溢出的,根据C++的语法规则,溢出后变成负数,此时结果就被更新成负数,题目中m的范围是5×103,其实我们可以把INF定义为1e8就可以。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2322497.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

simpleITK - Setup - Pythonic Syntactic Sugar

Pythonic Syntactic Sugar Image Basics Notebook 非常简单&#xff0c;与 ITK 的 C 接口非常接近。 Sugar非常棒&#xff0c;它能让你精力充沛&#xff0c;更快地完成任务&#xff01;SimpleITK 也应用了大量Sugar来帮助更快地完成任务。 %matplotlib inline import matplo…

下载vmware17

我用VMware10安装ubuntu24&#xff0c;死活不能成功&#xff0c;要么突然退出&#xff0c;要么装着装着&#xff0c;眼看完成&#xff0c;居然卡住不动&#xff0c;一查日志&#xff0c;提示光盘读取失败&#xff08;用的ISO文件&#xff0c;居然装模作样的说光驱读取失败&…

德昂观点:如何看待MicroStrategy改名为Strategy?

2025年2月&#xff0c;纳斯达克上市公司MicroStrategy&#xff08;股票代码&#xff1a;MSTR&#xff09;宣布更名为“Strategy”&#xff0c;并同步启用全新品牌标识与橙色主视觉。这不仅是品牌形象的更新&#xff0c;更是公司战略方向的明确宣示。德昂作为MSTR中国区BI合作伙…

嵌入式八股RTOS与Linux---网络系统篇

前言 关于计网的什么TCP三次握手 几层模型啊TCP报文啥的不在这里讲,会单独分成一个计算机网络模块   这里主要介绍介绍lwip和socket FreeRTOS下的网络接口–移植LWIP 实际上FreeRTOS并不自带网络接口,我们一般会通过移植lwip协议栈让FreeRTOS可以通过网络接口收发数据,具体可…

Django 生成 ssl 安全证书,切换 https、wss协议(daphne 、nginx)

Django 普通 http 协议不够安全&#xff0c;无法支持连接本地摄像头&#xff08;虽然在本地 localhost 上能连&#xff09;&#xff0c;此时需要切换成 https 协议&#xff08;先提个醒&#xff0c;我这个方法最后失败了&#xff0c;不过对您应该也有帮助&#xff09; 目录 配置…

告别Win10强制更新:永久关闭系统更新指南

你是否厌倦了Win10在开关机时的强制自动更新&#xff1f;无论你是在赶时间还是专注于工作&#xff0c;那突如其来的更新提示总是让人不胜其烦。屏幕上那句“正在更新&#xff0c;请勿关闭电源”的提示&#xff0c;仿佛是对你无奈的嘲笑。别担心&#xff0c;今天我将教你如何永久…

罗杰斯特回归

定义 逻辑回归其实就是原来的线性回归加了激活函数&#xff0c;这个函数其实就是sigmoid函数&#xff0c;把一个回归的连续数值压缩到了0到1的空间&#xff0c;其实只要有函数能够满足把数值压缩到0,1之间就可以&#xff08;因为0到1之间的数值就是概率值&#xff09; 对于分类…

【嵌入式学习2】C语言 - VScode环境搭建

目录 ## 语言分类 ## c语言编译器 ## VScode相关配置 ## 语言分类 编译型语言&#xff1a;C&#xff0c;C解释型语言&#xff1a;python&#xff0c;JS ## c语言编译器 分类GCC 系列MinGWCygwinMSVC系列一套编程语言编译器将GCC编译器和GNU Binutils移植到Win32平台下的产物…

利用脚本和Shader制作屏幕后处理效果

一、屏幕后处理的实现原理 该屏幕后处理的原理是将渲染完成后的屏幕纹理通过脚本和Shader完成一些操作&#xff0c;然后实现各种屏幕效果 而实现屏幕后处理效果的主要操作就是获得当下渲染完成后的屏幕图像&#xff0c;其中unity提供了一个函数用于获取此图像——OnRenderIma…

【银河麒麟系统常识】命令:uname -m(查看系统架构)

命令&#xff1a; uname -m 功能 常用的 Linux/Unix 终端命令&#xff0c;用于显示当前系统的硬件架构&#xff1b; 返回 返回系统的CPU架构类型&#xff0c;用于判断软件兼容性&#xff1b; 输出结果架构说明常见设备x86_64Intel/AMD 64位 CPU主流 PC、服务器aarch64ARM 64位 …

3.1.2 内存池

文章目录 3.1.2 内存池1. 什么是内存池2. 内存管理1. 定长2. 不定长3. jemalloc4. tcmalloc 3.1.2 内存池 1. 什么是内存池 内存池&#xff08;Memory Pool&#xff09; 是一种 预先分配 一块大内存&#xff0c;然后按需分配和回收 其中小块内存的技术。它的本质是管理一块连续…

基于SpringBoot + Vue 的餐厅点餐管理系统

SpringBootVue餐厅点餐管理系统 技术框架 后端&#xff1a;springboot mybatisPlus前端&#xff1a;Vue2 elementUI数据库&#xff1a;mysql项目构建工具&#xff1a;maven 数据库表 14张 角色及功能 管理员&#xff1a;登录、用户管理、餐桌信息管理、菜品类型管理、菜…

【博客节选】再谈Unity 的 root motion

节选自 【Unity实战笔记】第二十三 root motion变更方向攻击 &#xff08;OnStateMove rootmotion rigidbody 使用的一些问题&#xff09; 小伙伴们应该对root motion非常困惑&#xff0c;包括那个bake into pose。 当xz bake into pose后&#xff0c;角色攻击动画与父节点产…

26考研——栈、队列和数组_栈(3)

408答疑 文章目录 一、栈1、栈&#xff08;Stack&#xff09;的概念和特点定义术语操作特性示例直观理解栈的基本操作初始化栈判断栈是否为空入栈操作出栈操作读取栈顶元素销毁栈 栈的数学性质 2、栈的顺序存储结构顺序栈的定义栈顶指针初始化注意事项 共享栈共享栈的操作共享栈…

基于 mxgraph 实现流程图

mxgraph 可以实现复杂的流程图绘制。mxGraph里的Graph指的是图论(Graph Theory)里的图而不是柱状图、饼图和甘特图等图(chart)&#xff0c;因此想找这些图的读者可以结束阅读了。 作为图论的图&#xff0c;它包含点和边&#xff0c;如下图所示。 交通图 横道图 架构图 mxGrap…

动态路由机制MoE专家库架构在多医疗AI专家协同会诊中的应用探析

随着医疗人工智能技术的飞速进步,AI在医学领域的应用日益增多,尤其是在复杂疾病的诊断和治疗中,AI技术的应用带来了巨大的潜力。特别是动态路由机制混合专家(Mixture of Experts,MoE)架构,因其灵活、高效的特点,正逐渐成为实现多AI专家协同会诊的关键技术。通过将多个不…

双工通信:WebSocket服务

&#xff08;一&#xff09;WebSocket概述 WebSocket 是基于 TCP 的一种新的网络协议。它实现了浏览器与服务器全双工通信——浏览器和服务器只需要完成一次握手&#xff0c;两者之间就可以创建持久性的连接&#xff0c; 并进行双向数据传输 注意;Websocket也只能由客户端先握…

洪水灌溉算法 + 总结

文章目录 floodfill算法图像渲染题解代码 岛屿数量题解代码 岛屿的最大面积题解代码 被围绕的区域题解代码 太平洋大西洋水流问题题解代码 扫雷游戏题解代码 衣橱整理题解代码 总结 floodfill算法 1. 寻找相同性质的联通块&#xff0c;可以使用dfs或者bfs解决&#xff0c;比如…

LangChain4j(1):初识LangChain4j

1 什么是LangChain和LangChain4j LangChain是一个大模型的开发框架&#xff0c;使用LangChain框架&#xff0c;程序员可以更好的利用大模型的能力&#xff0c;大大提高编程效率。如果你是一个lava程序员&#xff0c;那么对LangChain最简单直观的理解就是&#xff0c;LangChain…

Photoshop 2025安装包下载及Photoshop 2025详细图文安装教程

文章目录 前言一、Photoshop 2025安装包下载二、Photoshop 2025安装教程1.解压安装包2.运行程序3.修改安装路径4.设安装目录5.开始安装6.等安装完成7.关闭安装向导8.启动软件9.安装完成 前言 无论你是专业设计师&#xff0c;还是初涉图像处理的小白&#xff0c;Photoshop 2025…