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

news/2024/11/6 7:14:13 标签: 算法, c++

目录

一、概念

二、思路

三、代码


一、概念

在前面的学习中,我们已经接触了Dijkstra、Bellman-Ford等单源最短路径算法。但首先我们要知道何为单源最短路径,何为多源最短路径

  • 单源最短路径:从图中选取一点,求这个点到图中其他节点的最短路径
  • 多源最短路径:从图中任选两个节点,我们都能知道这两点间的最短路径

Floyd多源最短路径算法可用于求图中任意两点间的最短路径长,其核心思路在于依次将每个节点作为路径的中间点来更新其他任意两点的较优解,最后得到全局最优解


二、思路

1.首先我们需要一个图,和二维数组g、path

其中:

  • g用于存储从i到j的最短路径长度
  • path用于存储从i到j的最短路径的终点 的 前继节点

例如初始时,从1到2的最短路径就是权重为6的边,其终点为2,而对于这条路径而言2的前继节点为1,因此path[1][2] = 1

g(0)和path(0)意为矩阵g和path的初始态。因为初始时两个节点之间的最短路径就是他们之间的边,因此我们在初始化这两个数组时,只需要按照样例输入的边填写矩阵g即可

若从i到j之间没有边,则填最大值即可,例如g[3][2] = MAX,因为没有从3指向2的边

而矩阵path在初始化时按照上面的规则初始化即可,例如初始从3到1的最短路径就是3->1,终点为1,前继节点为3,因此path[3][1] = 3

2. 从1号节点开始,将每个节点作为任意两个节点的最短路径的中间点

有的人听到这里可能已经懵了,我们跟着图慢慢走

此时g(0)、path(0)变为g(1)和path(1),代表接下来要更新 i->1->j 的最短路径

但是我们并不需要将矩阵g和矩阵path中的所有值都更新,例如g[1][2],判断1->1->2的路径是否比1->2的最短路径更短是不具有价值的。两个矩阵中,如果行标和中间节点一样、列标和中间节点一样或者行标和列标一样的话,我们直接跳过即可

因此,只有2->1->3的情况,和3->1->2的情况需要讨论

(带虚线的位置代表不需要判断)

可以看到,2->1->3的距离为2->1的最短距离加1->3的最短距离,即g[2][1]+g[1][3] = 23,这个距离并不比g[2][3]小,因此不需要更新

而3->1->2的距离为11,小于原来的值MAX,因此更新,同时path[3][2]也更新为3->1->2的终点的前继节点即1

3.重复第二步直到所有节点都已作为中间点

1->2->3的距离为g[1][2]+g[2][3] = 10,比原来的13更小,因此将g[1][3]更新,path[1][3] = 2

3->2->1的距离为g[3][2]+g[2][1] = 21,比g[3][1]大,不更新

1->3->2的距离为21,比g[1][2]大,不更新

2->3->1的距离为g[2][3]+g[3][1] = 9,比原来的10更小,因此将g[2][1]更新,path[2][1] = 3

至此,我们就得到了图中任意两点间的最短路径长度了

而最短路径本身,则可以根据矩阵path中的值推出来,例如要求从2到1的最短路径,首先知道终点为节点1,根据path[2][1]知道下一个节点3,再根据path[2][3]知道下一个节点2,最后path[2][2]为-1说明路径走到结尾,因此完整的最短路径就为2->3->1


三、代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define debug(x) cout << #x << " = " << x << '\n'
#define INF 0x3f3f3f3f
using namespace std;

#define N 210
#define M 20010

int n, m, k;
int g[N][N]; //存储从i到j的最短路径长度
int path[N][N] = {-1}; //path[i][j]存储从i到j最短路径的终点 的 前继节点

void Floyd()
{
    for(int i = 1; i <= n; i++)
	{
	    g[i][i] = 0; //自己到自己的路径长度设置为0
	    path[i][i] = -1; //自己到自己的路径设置为-1
	}
	
	for(int k = 1; k <= n; k++) //代表从i经过k到j的最短路径
	{
		for (int i = 1; i <= n; i++) //第i行
		{
			for (int j = 1; j <= n; j++) //第j列
			{
				if(i == j || i == k || j == k) //多余情况
					continue;

				if(g[i][k] + g[k][j] < g[i][j]) //从i经过k到j的最短路径 比 原先从i到j的最短路径更短
				{
					g[i][j] = g[i][k] + g[k][j]; //更新从i到j的最短路径
					path[i][j] = path[k][j]; //更新从i到j最短路径的终点 的 前继节点
				}
			}
		}
	}
}

void solve()
{
    memset(g, 0x3f, sizeof g);
	

	cin >> n >> m >> k;
	for(int i = 0;i < m; i++)
	{
	    int a, b, w;
	    cin >> a >> b >> w;
	    g[a][b] = min(g[a][b], w); //可能存在重边
		path[a][b] = a; //初始时从a到b最短路径终点的前继节点就是a本身
	}

	Floyd(); //Floyd算法

	for (int i = 0; i < k; i++)
	{
		int a, b;
		cin >> a >> b;
		if(g[a][b] > INF / 2)
			cout << "impossible" << endl;
		else
			cout << g[a][b] << endl;
	}
}

signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int t = 1;
    //cin >> t;
    while(t--)
        solve();
    return 0;
}

完.


http://www.niftyadmin.cn/n/5740545.html

相关文章

Python——Selenium快速上手+方法(一站式解决问题)

目录 前言 一、Selenium是什么 二、Python安装Selenium 1、安装Selenium第三方库 2、下载浏览器驱动 3、使用Python来打开浏览器 三、Selenium的初始化 四、Selenium获取网页元素 4.1、获取元素的实用方法 1、模糊匹配获取元素 & 联合多个样式 2、使用拉姆达表达式 3、加上…

CSS中的背景色和前景色

目录 1 对比度的计算1.1 亮度计算1.2 对比度比率 2 在线计算对比度 在我们的样式设计中&#xff0c;通常会有背景色和前景色的概念。前景色我们通常用来设置文本的颜色&#xff0c;而背景色通常是文本的所在容器的颜色。比如如果我们把文本放在普通容器里&#xff0c;那普通容器…

[C++]——哈希(附源码)

目录 ​编辑 ​编辑 一、前言 二、正文 2.1 unorder系列关联式容器 2.1.1 unordered_map 2.1.1.1 unorderer_map的介绍 ①unordered_map的构造 ②unordered_map的容量 ③unordered_map的迭代器 ④unordered_map的元素访问 ⑤unordered_map的查询 ⑥unordered_map的修改操…

写文件回前端进行下载,报错:原因:CORS 头缺少 ‘Access-Control-Allow-Origin‘)

后端写文件返回前端&#xff0c;出现该错误。 解决 设置允许跨域 response.setHeader("Access-Control-Allow-Origin", "*"); 代码 后端 public void exportTemplate(HttpServletResponse response) { ArrayList<ActiveGifts> activeGifts new…

面试总结!

OSI七层模型&#xff1a; 什么是OSI七层模型&#xff1f; 我们需要了解互联网的本质是一系列的网络协议&#xff0c;这个协议就叫做OSI协议&#xff08;开放系统互联(Open System Interconnection&#xff09;&#xff09;&#xff0c;它是由ISO&#xff08;国际标准化组织&…

给初学者的 Jupyter Notebook 教程

目录 一、什么是Jupyter Notebook&#xff1f; 1. 简介 2. 组成部分 ① 网页应用 ② 文档 3. Jupyter Notebook的主要特点 二、安装Jupyter Notebook 0. 先试用&#xff0c;再决定 1. 安装 ① 安装前提 ② 使用Anaconda安装 ③ 使用pip命令安装 三、运行Jupyter No…

商务礼仪与职场沟通

知人者智&#xff0c;自知者明。胜人者有力&#xff0c;自胜者强。知足者富&#xff0c;强行者有志&#xff0c;不失其所者久&#xff0c;死而不亡者寿。 ——《道德经&#xff08;第三十三章&#xff09;》 认知先行——意识塑造 职业化——标准化&#xff0c;规范化&#…

(十三)JavaWeb后端开发——MySQL2

目录 1.DQL数据查询语言 1.1基本查询 1.2条件查询 where关键字 1.3分组查询 1.4排序查询 1.5分页查询 2.多表设计 3.多表查询——联查 4.多表查询——子查询​ 5.MySQL 事务 6.MySQL 索引 1.DQL数据查询语言 分为五大基本查询语法 1.1基本查询 -- 查询特定字段 s…