FloydWarshall多(所有)源点的最短路径实现(带路径打印)

17 篇文章 0 订阅
1 篇文章 0 订阅

一、介绍和算法原理:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
https://www.cs.usfca.edu/~galles/visualization/Floyd.html

二、核心代码:

dist[i][j]表示从ij的最短距离,parent[i][j]表示源点为i时,j的双亲是谁,一开始我都初始化parent[i][j] = i
下面的是这个算法的核心代码,书上讲的挺好的,dist(k)[i][j]表示从ij,中间由序号不大于k的顶点序号(可能是多个)作为中转点时,ij的最短路径。

	for(int k = 0; k < V; k++)
	{
		for(int i = 0; i < V; i++)
		{
			for(int j = 0; j < V; j++)
			{
				if(dist[i][k] + dist[k][j] < dist[i][j])
				{
					dist[i][j] = dist[i][k] + dist[k][j]; 
					parents[i][j] = parents[k][j];	 
				}
			}
		}
	}

1. 这里外循环k=0,里面两层循环尝试更新所有i-->jk=0为中间节点时的最短距离。可能会出现这些情况,1-->0-->5,2-->0-->3,3-->0-->1,(0-->0-->5这种就没意义)
2. 当k=1时,尝试所有i->1->j路径,因为上一步k=0的时候检查过1->0->(0,1,2...n-1)会不会让1到其他各点的距离会不会变短,所以这个i->1->j是在上一步的基础上的,即2-->1--->5可能代表的这条路径2-->1-->0-->53-->1--->4可能代表的这条路径3-->1-->0-->4,当然0-->1--->4也是可能的。
3. k=2时,尝试以2为中间点(事实上是尝试把2加到中间点序列),即0-->2-->5可能代表着0-->1-->2-->5,3-->2-->6可能代表着3-->1-->2-->0---->6,但是不会出现3-->5--->1--->6这种情况,因为5还没做为中间结点去检查过。
4…
5…

在内外循环结束之后,所有结点都尝试被当做中间结点加入ij的路径中去了,所以得到dist[i][j]ij的最短路径了。

二、全部代码:

#include<iostream>
#include<vector>

using namespace std;

#define INF 999999	//不可能的权值 
#define V 6			//顶点数 
void printSolution(int dist[][V],int parents[][V],int graph[][V])
{
	cout<<"打印任一对顶点间的最短路径,"
		<<"若weight为INF和dist[i][j]为INF则表示i->j无路径"<<endl;  
	for(int i = 0; i < V; i++)
	{
		cout<<"------从"<<i<<"出发到各顶点的最短路径:-------"<<endl; 
		for(int j = 0; j < V; j++)
		{
			cout<<parents[i][j]<<" --> "<<j<<" \t weight is :";
			
			int parent = parents[i][j];
			
			if (graph[parent][j] == INF)  
                cout<<"INF"<<"     ";  
            else
                cout<<graph[parent][j]<<"     ";
					 
			cout<<" dist["<<i<<"]["<<j<<"] is ";
			
			if (dist[i][j] == INF)  
                cout<<"INF"<<endl;  
            else
                cout<<dist[i][j]<<endl;	 
		}
		cout<<endl;
	}
}
void floydWarshall(int graph[][V])
{
	int dist[V][V]; 
	int parents[V][V];	//parent[i][0...V-1]是从第i个元素
						//出发的双亲数组,用来记录路径 
	
	for(int i = 0; i < V; i++)
	{
		for(int j = 0; j < V; j++)
		{
			dist[i][j] = graph[i][j];
			//从i出发时将i视为其他顶点的双亲,若后面变了,说明加了中转顶点 
			parents[i][j] = i; 	
		} 
	}
	
	for(int k = 0; k < V; k++)
	{
		for(int i = 0; i < V; i++)
		{
			for(int j = 0; j < V; j++)
			{
				if(dist[i][k] + dist[k][j] < dist[i][j])
				{
					dist[i][j] = dist[i][k] + dist[k][j]; 
					parents[i][j] = parents[k][j];	 
				}
			}
		}
	}
	printSolution(dist,parents,graph);
}
int main()
{
	int graph[V][V] = { {0,   INF,  10, INF, 30,  100},  
                        {INF,   0,   5, INF, INF, INF},  
                        {INF, INF,   0,  50, INF,   1},  
                        {INF, INF, INF,   0, INF,  10}, 
						{INF, INF, INF,  20,   0,  60},
						{INF, INF, INF,   0, INF,   0}, 
                      }; 
    floydWarshall(graph);
	return 0; 
}

输出:

打印任一对顶点间的最短路径,若weight为INF和dist[i][j]为INF则表示i->j无路径
------0出发到各顶点的最短路径:-------
0 --> 0          weight is :0      dist[0][0] is 0
0 --> 1          weight is :INF      dist[0][1] is INF
0 --> 2          weight is :10      dist[0][2] is 10
5 --> 3          weight is :0      dist[0][3] is 11
0 --> 4          weight is :30      dist[0][4] is 30
2 --> 5          weight is :1      dist[0][5] is 11

------1出发到各顶点的最短路径:-------
1 --> 0          weight is :INF      dist[1][0] is INF
1 --> 1          weight is :0      dist[1][1] is 0
1 --> 2          weight is :5      dist[1][2] is 5
5 --> 3          weight is :0      dist[1][3] is 6
1 --> 4          weight is :INF      dist[1][4] is INF
2 --> 5          weight is :1      dist[1][5] is 6

------2出发到各顶点的最短路径:-------
2 --> 0          weight is :INF      dist[2][0] is INF
2 --> 1          weight is :INF      dist[2][1] is INF
2 --> 2          weight is :0      dist[2][2] is 0
5 --> 3          weight is :0      dist[2][3] is 1
2 --> 4          weight is :INF      dist[2][4] is INF
2 --> 5          weight is :1      dist[2][5] is 1

------3出发到各顶点的最短路径:-------
3 --> 0          weight is :INF      dist[3][0] is INF
3 --> 1          weight is :INF      dist[3][1] is INF
3 --> 2          weight is :INF      dist[3][2] is INF
3 --> 3          weight is :0      dist[3][3] is 0
3 --> 4          weight is :INF      dist[3][4] is INF
3 --> 5          weight is :10      dist[3][5] is 10

------4出发到各顶点的最短路径:-------
4 --> 0          weight is :INF      dist[4][0] is INF
4 --> 1          weight is :INF      dist[4][1] is INF
4 --> 2          weight is :INF      dist[4][2] is INF
4 --> 3          weight is :20      dist[4][3] is 20
4 --> 4          weight is :0      dist[4][4] is 0
3 --> 5          weight is :10      dist[4][5] is 30

------5出发到各顶点的最短路径:-------
5 --> 0          weight is :INF      dist[5][0] is INF
5 --> 1          weight is :INF      dist[5][1] is INF
5 --> 2          weight is :INF      dist[5][2] is INF
5 --> 3          weight is :0      dist[5][3] is 0
5 --> 4          weight is :INF      dist[5][4] is INF
5 --> 5          weight is :0      dist[5][5] is 0


--------------------------------
Process exited with return value 0
Press any key to continue . . .
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值