Floyd算法
核心思路:
通过一个图的权值求出它每两点之间的最短路,也可求解多源最短路
从带权的图a中,递归地进行n次更新,构造出距离矩阵。
采用松弛操作,对在i和j之间的点做一次松弛。
时间复杂度为O(n^3)
动态转移方程:
Map[i][j]=min{
Map[i][j]+Map[k][j],
Map[i][j]
}
Map[i][j]表示i到j的最短距离,k是穷举i,j的断点。
最短距离有三种情况:
1、两点的直达距离最短。
2、两点间只通过一个中间点而距离最短。
3、两点间用通过两各以上的顶点而距离最短。
算法过程:
1. 从一条边开始,两点之间的距离是边的权,如果两点之间没有边,就可以默认权无穷大。从任意节点i到任意节点j的最短路径不外乎2种可能,1是直接从i到j,2是从i经过若干个节点k到j。所以,我们假设Dis(i,j)为节点u到节点v的最短路径的距离,对于每一个节点k,我们检查Dis(i,k) + Dis(k,j) < Dis(i,j)是否成立,如果成立,证明从i到k再到j的路径比i直接到j的路径短,我们便设置Dis(i,j) = Dis(i,k) + Dis(k,j),这样一来,当我们遍历完所有节点k,Dis(i,j)中记录的便是i到j的最短路径的距离。
2. 对于每一对顶点u和v,看看是否存在一个顶点w使得u到v之间中转更短,如果是则更新它。
例如有图如下:
这就是一个多源最短路,也就是求任意两点的距离。
那矩阵e为:
0 |
2 |
6 |
4 |
无穷 |
0 |
3 |
无穷 |
7 |
无穷 |
0 |
1 |
5 |
无穷 |
12 |
0 |
|
|
|
Floyd算法过程矩阵的计算----十字交叉法
方法:两条线,从左上角开始计算一直到右下角
这个算法过程虽说麻烦,但核心代码只有5行:
1 void Floyd()
{
2 int i,j,k;
3 for(k=1;k<=n;k++)
4 for(i=1;i<=n;i++)
5 for(j=1;j<=n;j++)
6 if(dist[i][k]+dist[k][j]<dist[i][j])
7 dist[i][j]=dist[i][k]+dist[k][j];
8 }
复杂度:
由于代码:
16 for(k=1;k<=n;k++)
17 for(i=1;i<=n;i++)
18 for(j=1;j<=n;j++)
19 if(e[i][j]>e[i][k]+e[k][j])
20 e[i][j]=e[i][k]+e[k][j];
所以显而易见,此算法需要O(n^3)的时间复杂度
空间复杂度有二维数组,所以为O(n^2)
Floyd算法属于一种动态规划思想的算法,简单有效,效率高于执行N次Dijkstra算法,也高于执行N次spfa算法,但是此算法时间复杂度较高,所以不适合计算大数据。
整体核心代码:
for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);