Floyed算法(任意两点间的最短路)

Graph图论

Floyed算法(任意两点间的最短路)

可以处理存在负边的情况,也可以判断是否存在负环。
对于最短路我们之前接触的都是单源最短路径,即起点固定,求该点开始到其他点的最短路径,但是如果我们想要求得任意两点间的最短路径,难道要对每一个点都要进行一遍dijkstra?显然比较麻烦,并且还不好存储信息,那么我们就要用到Floyed算法了。
在这里我们用到一个dp数组dp[ i ][ j ]:从 i 到 j 所需要的最短距离,其实把数组的作用想明白了算法也就完成了大半,那么我们假设有一个点k,那么我们从 i 到 j 可以有两种情况,一种是最短路径上经过 k再到 j ,一种是不经过 k ,那么动态转移方程就很好写了:
dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]
想好动态数组和动态转移方程,那么就只剩下初始化了,因为最开始的时候我们有的是一条条直达的道路,假设我们知道a->b的路程是c,那么我们初始化的时候就让dp[a][b] = c;,其余不能直达的就初始化为INF,即dp[a][d] = INF;自己到自己的距离为0,即dp[i][i] = 0;
Floyed算法跟Bellman_Ford一样,都可以处理负边权的问题,并且判断图中是否存在负环只需要检查是否存在dp[i][j]是负数的边就好了。
完整代码如下:

#include<iostream>
#include<cstring>
using namespace std;
long long dp[10001][10001];
void floyed(int n){
	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]);
			}
		}
	}
}
int main(){
	int n,m;
	cin >> n >> m;
	memset(dp,0x7f7f7f7f,sizeof(dp));
	for(int i=1;i<=n;i++){
		dp[i][i] = 0;
	}
	for(int i=0;i<m;i++){
		int a,b;
		long long c;
		cin >> a >> b >> c;
		dp[a][b] = min(dp[a][b],c);	
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cout << dp[i][j] << " ";
		}
		cout << endl;
	}
	floyed(n);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			cout << dp[i][j] << " ";
		}
		cout << endl;
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Floyd算法(也称为Floyd-Warshall算法)是一种用于寻找加权图中最短路径的算法。它可以用来解决带有负权边的图的最短路径问题。在C语言中,实现Floyd算法需要以下步骤: 1. 定义一个二维数组来存储图的邻接矩阵。 2. 初始化邻接矩阵,将不存在的边的距离设置为无穷大,将存在的边的距离设置为它们的权值。 3. 进行三重循环,其中第一重循环控制中节点,第二重循环控制起点,第三重循环控制终点。在循环过程中,计算每对节点之最短路径,并更新邻接矩阵中的距离。 4. 最后,输出邻接矩阵中的最短路径矩阵即可。 具体实现可以参考以下示例代码: ```c #include <stdio.h> #define MAX 1000000 //定义一个无穷大的距离 int main() { int n, m; //n表示点的个数,m表示边的个数 scanf("%d %d", &n, &m); int graph[n][n]; //定义邻接矩阵 int i, j, k; //初始化邻接矩阵 for(i=0; i<n; i++) { for(j=0; j<n; j++) { graph[i][j] = (i == j) ? 0 : MAX; } } //读入边的信息,并更新邻接矩阵 int u, v, w; for(i=0; i<m; i++) { scanf("%d %d %d", &u, &v, &w); graph[u][v] = w; } //Floyd算法核心代码 for(k=0; k<n; k++) { for(i=0; i<n; i++) { for(j=0; j<n; j++) { if(graph[i][k] + graph[k][j] < graph[i][j]) { graph[i][j] = graph[i][k] + graph[k][j]; } } } } //输出最短路径矩阵 for(i=0; i<n; i++) { for(j=0; j<n; j++) { if(graph[i][j] == MAX) { printf("INF "); } else { printf("%d ", graph[i][j]); } } printf("\n"); } return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值