码迷,mamicode.com
首页 > 其他好文 > 详细

Floyd最短路径算法

时间:2014-09-12 13:31:46      阅读:332      评论:0      收藏:0      [点我收藏+]

标签:算法   迭代   递归   algorithm   

Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。
通过一个图的权值矩阵求出它的每两点间的最短路径矩阵
从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。
采用的是(松弛技术),对在i和j之间的所有其他点进行一次松弛。所以时间复杂度为O(n^3);

bubuko.com,布布扣为从bubuko.com,布布扣bubuko.com,布布扣的只以bubuko.com,布布扣集合中的节点为中间节点的最短路径的长度。

  1. 若最短路径经过点k,则bubuko.com,布布扣
  2. 若最短路径不经过点k,则bubuko.com,布布扣

因此,bubuko.com,布布扣


状态转移方程如下: D[i,j]:=min{D[i,j],D[i,k]+D[k,j]}
map[i,j]表示i到j的最短距离,K是穷举i,j的断点,D[n,n]初值应该为0,或者按照题目意思来做。
当然,如果这条路没有通的话,还必须特殊处理,比如没有D[i,k]这条路。

Floyd-Warshall算法的时间复杂度bubuko.com,布布扣空间复杂度bubuko.com,布布扣

Floyd-Warshall算法的描述如下:

for k  1 to n do
  for i  1 to n do
    for j  1 to n do
      if (bubuko.com,布布扣) then
        bubuko.com,布布扣  bubuko.com,布布扣;

其中bubuko.com,布布扣表示由点bubuko.com,布布扣到点bubuko.com,布布扣的代价,当bubuko.com,布布扣为 ∞ 表示两点之间没有任何连接。

在实际算法中,为了节约空间,可以直接在原来空间上进行迭代,这样空间可降至二维。

大概的代码为:

 for(int k=1;k<=n;k++)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(ans[k-1][i][k]==无穷大||ans[k-1][k][j]==无穷大)
                {
                    ans[k][i][j]=ans[k-1][i][j]; //保持原来的值,即从i到j允许经过前k个点和允许经过前k-1个节点时最短路径长度相同
                    continue;
                }
                if(ans[k-1][i][j]==无穷大||ans[k-1][i][k]+ans[k-1][k][j]<ans[k-1][i][j])
                {
                    ans[k][i][j]=ans[k-1][i][k]+ans[k-1][k][j];
                }
                else
                {
                    ans[k][i][j]=ans[k-1][i][j];
                }
            }
        }
    }
经过这么多次迭代后,最后a到b的最短路径结果为ans[n][a][b].

与此同时,我们注意到,在通过ans[k-1][i][j]的值来递推求ans[k][i][j]的值时,所有的ans[k][i][j]值将由ans[k-1][i][j]与ans[k-1][i][k]+ans[k-1][k][j]的大小关系来确定,但同时ans[k][i][k]和ans[k][k][j]必定与ans[k-1][i][k]和ans[k-1][k][j]的值是相同的,即这些值不会因为本次更新而发生变化。所以我们将代码简化为:

for(int k=1;k<=n;k++){
    for(int i=1;i<=n;i++){
          for(int j=1;j<=n;j++){
                if(ans[i][k]==无穷大||ans[k][j]==无穷大) continue;
                if(ans[i][j]==无穷大||ans[i][k]+ans[k][j]<ans[i][j])
                  {
                   ans[i][j]=ans[i][k]+ans[k][j];
                  }
           }
     } 
   }
    这样原本空间复杂度O(N3)变为O(N2)了。每次跟新直接在该二位数组上就OK。



Floyd最短路径算法

标签:算法   迭代   递归   algorithm   

原文地址:http://blog.csdn.net/alvine008/article/details/39206657

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!