一、介绍和算法原理:
https://www.cs.usfca.edu/~galles/visualization/Floyd.html
二、核心代码:
dist[i][j]
表示从i
到j
的最短距离,parent[i][j]
表示源点为i
时,j
的双亲是谁,一开始我都初始化parent[i][j] = i
下面的是这个算法的核心代码,书上讲的挺好的,dist
(k)
[i][j]
表示从i
到j
,中间由序号不大于k
的顶点序号(可能是多个)作为中转点时,i
与j
的最短路径。
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-->j
以k=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-->5
,3-->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…
…
在内外循环结束之后,所有结点都尝试被当做中间结点加入i
与j
的路径中去了,所以得到dist[i][j]
就i
到j
的最短路径了。
二、全部代码:
#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 . . .