设Lij(m)为i到j经过m条边的算法
则Lij(m)=min(Lij(m-1),min(Lik(m-1)+wik)(for k=1到n))
(每次累加一条边,做n次就可以了)
这样做的原因:最短路径有最优子结构,对于M条边的最短路径,假设用邻接矩阵来表示,那么从i到j的一条最短路径p,假设p最多m条边,如果i=j,那么p=0,如果i和j不同,把路径p分解为i->k->j其中i到k最多m-1条边,那么根据最优子结构,这m-1条边也必须是一个最短路径。所以我们只要在最短路径的基础上往下推一个就可以了。
for(int m=0;m<n;m++) for(int i=0;i<n;i++) for(int j=0;j<n;j++) for(int k=0;k<n;k++) l[i][j]=min(l[i][j],l[i][k]+w[k][j]);时间复杂度是O(n^4) 如果不算出全部矩阵,可以简化成O(N3lgn)
弗洛伊德算法
1 // dist(i,j) 为从节点i到节点j的最短距离
2 For i←1 to n do
3 For j←1 to n do
4 dist(i,j) = weight(i,j)
5
6 For k←1 to n do // k为“媒介节点”
7 For i←1 to n do
8 For j←1 to n do
9 if (dist(i,k) + dist(k,j) < dist(i,j)) then // 是否是更短的路径?
10 dist(i,j) = dist(i,k) + dist(k,j)
朴素的算法,从本质上来说,是一步一步的跨越,而弗洛伊德算法实现了从上一步到中间节点的跨越
弗洛伊德算法的k取自中间节点,中间节点全部为1,到全部为n的变换。
算导P405讲的非常好
这是一个从i到k,从k到j的计算方式媒介节点从1到k
(媒介为1,2,......K的最短路径)