Floyd算法
Floyd算法是求任意图中任意两个节点的最短路径的算法,一般认为Floyd算法使用了动态规划策略。即对任意一条最短路径u ~v, 假如k在该路径中,则改最短路径可以表示为u ~k~v。
设Di,j,k为从i到j的只以(1..k)集合中的节点为中间节点的最短路径的长度。
- 若最短路径经过点k,则Di,j,k = Di,k,k − 1 + Dk,j,k − 1;
- 若最短路径不经过点k,则Di,j,k = Di,j,k − 1。
因此,Di,j,k = min(Di,k,k − 1 + Dk,j,k − 1, Di,j,k − 1)。
在实际算法中,为了节约空间,可以直接在原来空间上进行迭代, 并且Di,j,k 是肯定会比Di,k,k − 1 小的,所以算法伪代码如下
for(k = 1; k <= D.size; ++k)
for(i = 1; i <= D.size; ++i)
for(j = 1; j <= D.size; ++j)
D[i][j] = D[i][j] < D[i][k] + D[k][j] ? D[i][j] : D[i][k] + D[k][j]
换一种思路理解,每次最外层循环,都把所有从k节点出发的边进行了一次松弛操作。假设存在这样一条最短路径 u -> k+2 -> k+1 -> v,那么在对k+1层循环时k+2 -> k+1 -> k的最短路径被确定, 然后在k+2次循环时,u -> k+2 -> k+1 -> v的最短路径被确定,结合松弛操作的性质,一旦某跳最短路径的估计权重被缩小到实际的最短路径权重,它的值将不会改变,所以最后求到的路径就一定是最短路径。
vector<vector<int>> floyd(vector<vector<int>> &g){ vector<vector<int>> sp(g.size(), vector<int>(g[0].size())); for(int i = 0; i < g.size(); ++i) { for(int j = 0; j < g.size(); ++j) { sp[i][j] = g[i][j]; } } for(int k = 0; k < g.size(); ++k) { for(int i = 0; i < g.size(); ++i) { for(int j = 0; j < g.size(); ++j) { sp[i][j] = sp[i][j] > sp[i][k] + sp[k][j] ? sp[i][k] + sp[k][j] : sp[i][j]; } } } return sp; }
浙公网安备 33010602011771号