算法竞赛备赛——【图论】求最短路径——Floyd算法

floyd算法

基于动态规划

应用:求多源最短路 时间复杂度:n^3

dijkstra:不能解决负边权

floyd:能解决负边权 不能解决负边权回路问题

求最短路径:dijkstra bfs floyd

思路

1.让任意两点之间的距离变短:引入中转点k

通过k来中转 i---->k---->j < i----->j

2.找状态:

n个点都可以做中转点的情况下,i到j之间的最短路径的长度是x

最终状态:dp[n][i][j]=x;

中间状态:dp[k][i][j]=x;经过前k个点(1~k)做中转点的情况下,i到j之间的最短路径的长度是x

初始状态:dp[0][i][j]=a[i][j];

3.找状态转移方程

经过前k个点(1~k)做中转点的情况下,i到j之间的最短路径的长度是?

中间状态:dp[k][i][j]=?

前k-1个状态已知,前k-1个点(1~k-1)做中转点的情况下,i到j之间的最短路径的长度

if(dp[k][i][j]>dp[k-1][i][k]+dp[k-1][k][j])

dp[k][i][j]=dp[k-1][i][k]+dp[k-1][k][j]

else

dp[k][i][j]=dp[k-1][i][j];

代码实现

C++ 复制代码
#include<iostream> 
using namespace std;
#define inf 0x7fffffff
int n, m;
int a[105][105];//邻接矩阵存图
int dp[105][105][105];

int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			a[i][j] = inf;
			if (i == j) {
				a[i][j] = 0;
			}
		}
	}
	int x, y, w;
	for (int i = 1; i <= m; i++) {
		cin >> x >> y >> w;
		a[x][y] = w;
	}

	//初始化dp
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			dp[0][i][j] = a[i][j];
		}
	}
	for (int k = 1; k <= n; k++) {//枚举中转点
		for (int i = 1; i <= n; i++) {//枚举起点、终点
			for (int j = 1; j <= n; j++) {
				dp[k][i][j] = min(dp[k - 1][i][j], dp[k - 1][i][k] + dp[k - 1][k][j]);
			}
		}
	}
	//输出
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cout << dp[n][i][j] << " ";
		}
	}
	return 0;
}

降维

C++ 复制代码
#include<iostream> 
using namespace std;
//降维 三维降为二维
#define inf 0x7fffffff
int n, m;
int a[105][105];//邻接矩阵存图
int dp[105][105]; 

int main() {
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			a[i][j] = inf;
			if (i == j) {
				a[i][j] = 0;
			}
		}
	}
	int x, y, w;
	for (int i = 1; i <= m; i++) {
		cin >> x >> y >> w;
		a[x][y] = w;
	}

	//初始化dp
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			dp[i][j] = a[i][j];
		}
	}
	//三重循环的顺序不能变换
	for (int k = 1; k <= n; k++) {//最外层一定是 枚举中转点
		for (int i = 1; i <= n; i++) {//枚举起点、终点
			for (int j = 1; j <= n; j++) {
				dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
			}
		}
	}
	//输出
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			cout << dp[i][j] << " ";
		}
	}
	return 0;
}
相关推荐
ajassi20002 小时前
开源 C++ QT Widget 开发(十五)多媒体--音频播放
linux·c++·qt·开源
焦耳加热3 小时前
阿德莱德大学Nat. Commun.:盐模板策略实现废弃塑料到单原子催化剂的高值转化,推动环境与能源催化应用
人工智能·算法·机器学习·能源·材料工程
wan5555cn3 小时前
多张图片生成视频模型技术深度解析
人工智能·笔记·深度学习·算法·音视频
u6063 小时前
常用排序算法核心知识点梳理
算法·排序
鹅毛在路上了4 小时前
C++, ffmpeg, libavcodec-RTSP拉流,opencv实时预览
c++·opencv·ffmpeg
John_ToDebug5 小时前
定制 ResourceBundle 的实现与 DuiLib 思想在 Chromium 架构下的应用解析
c++·chrome·ui
蒋星熠5 小时前
Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物
开发语言·python·算法·flutter·设计模式·性能优化·硬件工程
小欣加油6 小时前
leetcode 面试题01.02判定是否互为字符重排
数据结构·c++·算法·leetcode·职场和发展
3Cloudream6 小时前
LeetCode 003. 无重复字符的最长子串 - 滑动窗口与哈希表详解
算法·leetcode·字符串·双指针·滑动窗口·哈希表·中等
王璐WL6 小时前
【c++】c++第一课:命名空间
数据结构·c++·算法