算导-floyd-warshall算法

朴素的最短多远路径算法:

设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)
(这里k的意义:媒介,先走m-1步到k,再走一步到j。对于每个确定的i,j,进行一次查找,看能否从k那里借道更短)


弗洛伊德算法

 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的最短路径)

你可能感兴趣的:(算导-floyd-warshall算法)