Floyd-Warshall 所有结点对的最短路径算法

以下代码仅支持结点是顺序的,比如输入5个结点,结点的编号只能是1到5,输入顺序可以不一致。要正常输出也可以,但是到输出那个小的矩阵就麻烦了,于是就这样简单写了。

动态规划真的简洁,三个 for 把这么复杂的东西就整理好了。
递推公式:**d[i][j] = min ( d[i][j] , d[i][k] + d[k][j] ) **

动态规划重点在于递归式:
不要看字,看这个图!!!就很容易理解下面那个递归式了
在这里插入图片描述

在这里插入图片描述
维护了两个矩阵,一个权重的矩阵(做计算)和一个前驱矩阵(输出)

#include "stdafx.h"
#include <stdio.h>
#define inf 0x3f3f3f3f
#define N 100
int e[N][N],parent[N][N];
int k, i, j;     //循环变量
int n, m;        //n是结点数,m是边数

void Print_Shortest_Path(int i,int j)    //递归输出
{
	if (i == j)
		printf("%d  ", i);
	else if (parent[i][j] == NULL)
		printf("no path \n");
	else
	{
		Print_Shortest_Path(i, parent[i][j]);
		printf("%d  ", j);
	}
}

void Floyd_Warshall()
{
	for (k = 1; k <= n; k++)
	{
		for (i = 1; i <= n; i++)
		{
			for (j = 1; j <= n; j++)
			{
				if (e[i][j] > e[i][k] + e[k][j])
				{
					e[i][j] = e[i][k] + e[k][j];
					parent[i][j] = parent[k][j];
				}
			}
		}
	}
	//输出各点到各点的最小路径
	printf("\n最短路径矩阵:\n");
	for (i = 1; i <=n; i++)
	{
		for (j = 1; j <= n; j++)
		{
			if (e[i][j] != inf)
			{
				printf("%5d  ", e[i][j]);
			}
		}
		printf("\n");
	}
	printf("\n前驱矩阵:\n");
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= n; j++)
		{
			printf("%5d  ", parent[i][j]);
		}
		printf("\n");
	}
	printf("\n结点间最短距离的情况:\n");
	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= n; j++)
		{
			printf("%d --> %d : ", i, j);
			Print_Shortest_Path(i, j);
			printf("\n");
		}
		printf("\n");
	}
}

int main()
{
	int  t1, t2, t3;
	scanf_s("%d %d", &n, &m);

	for (i = 1; i <= n; i++)
	{
		for (j = 1; j <= n; j++)
		{
			if (i == j)              //矩阵的对角线是0,自己到自己的距离是0
			{
				e[i][j] = 0;
				parent[i][j] = NULL;
			}
			else
			{
				e[i][j] = inf;        //表示不通达
				parent[i][j] = i;
			}
		}
	}
	for (i = 1; i <= m; i++)
	{
		scanf_s("%d %d %d", &t1, &t2, &t3);
		e[t1][t2] = t3;                    //起点t1点到终点t2点的距离是t3
	}
	Floyd_Warshall();
	return 0;
}




在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/alike_meng/article/details/84204087
今日推荐