图的最短路径弗洛伊德Floyd算法

来源:互联网 发布:词组贝多芬知乎 编辑:程序博客网 时间:2024/06/05 11:21

弗洛伊德算法简介:

顶点对之间的最短路径是指:对于给定的有向网G=(V,E),要对G中任意一对顶点有序对V、W(V≠W),找出V到W的最短距离和W到V的最短距离。

    解决此问题的一个有效方法是:轮流以每一个顶点为源点,重复执行迪杰斯特拉算法n次,即可求得每一对顶点之间的最短路径,总的时间复杂度为O(n3)。

弗洛伊德(Floyd)提出了另外一个求图中任意两顶点之间最短路径的算法,虽然其时间复杂度也是 O(n3),但其算法的形式更简单,易于理解和编程。

算法基本思想

弗洛伊德算法仍然使用图的邻接矩阵arcs[n+1][n+1]来存储带权有向图。算法的基本思想是:设置一个n x n的矩阵A(k),其中除对角线的元素都等于0外,其它元素a(k)[i][j]表示顶点i到顶点j的路径长度,K表示运算步骤。开始时,以任意两个顶点之间的有向边的权值作为路径长度,没有有向边时,路径长度为∞,当K=0时, A (0)[i][j]=arcs[i][j],以后逐步尝试在原路径中加入其它顶点作为中间顶点,如果增加中间顶点后,得到的路径比原来的路径长度减少了,则以此新路径代替原路径,修改矩阵元素。具体做法为:  

第一步,让所有边上加入中间顶点1,取A[i][j]与A[i][1]+A[1][j]中较小的值作A[i][j]的值,完成后得到A(1),

第二步,让所有边上加入中间顶点2,取A[i][j]与A[i][2]+A[2][j]中较小的值,完成后得到A(2)…,如此进行下去,当第n步完成后,得到A(n),A(n)即为我们所求结果,A(n)[i][j]表示顶点i到顶点j的最短距离。    

因此,弗洛伊德算法可以描述为:

       A(0)[i][j]=arcs[i][j];               //arcs为图的邻接矩阵

       A(k)[i][j]=min{A(k-1) [i][j],A(k-1) [i][k]+A(k-1) [k][j]}

其中 k=1,2,…,n

定义一个n阶方阵序列:

           D(-1), D(0), …, D(n-1).

   其中 D(-1) [i][j] = G.arcs[i][j];

             D(k) [i][j] = min { D(k-1)[i][j],D(k-1)[i][k] + D(k-1)[k][j] }, k = 0,1,…, n-1

   D(0) [i][j]是从顶点vi 到vj , 中间顶点是v0的最短路径的长度,   

   D(k) [i][j]是从顶点vi 到vj , 中间顶点的序号不大于k的最短路径长度,

   D(n-1)[i][j]是从顶点vi 到vj 的最短路径长度。

例子:


实现:该代码已经在VC++6.0成功运行。

#include<iostream>


using namespace std;


#define INFTY 65535 
//没有边相邻用INFTY代替

//存储图的邻接矩阵


int m[4][4]={{0,1,INFTY,4},{INFTY,0,9,2},{3,5,0,8},{INFTY,INFTY,6,0}};


class MGraph


{


      public:


             MGraph(int size);


             ~MGraph();


             void Floyd();


             void shortestway(int u,int v);


      private:


              int **a,**d,**path;


              int n;


};


MGraph::MGraph(int size)


{


   n=size;


   a=new int*[n];


   for(int i=0;i<n;++i)


     a[i]=new int[n];


    


   for( i=0;i<n;++i)


     for(int j=0;j<n;++j)


          a[i][j]=m[i][j];


}


MGraph::~MGraph()


{


   for(int i=0;i<n;++i)


      delete []a[i];


   delete []a;


   a=NULL;


  


   for( i=0;i<n;++i)


     delete []d[i];


   delete []d;


   d=NULL;


  


   for( i=0;i<n;++i)


      delete []path[i];


   delete []path;


   path=NULL;


}


void MGraph::Floyd()


{


     int i,j,k;


     d=new int*[n];


     path=new int*[n];


     for( i=0;i<n;++i)


     {


        d[i]=new int[n];


        path[i]=new int[n];


        for(j=0;j<n;++j)


        {


           d[i][j]=a[i][j];


           if(i!=j && m[i][j]<INFTY) path[i][j]=i;


           else path[i][j]=-1;


        }


     }


     for(k=0;k<n;++k)


       for(i=0;i<n;++i)


         for(j=0;j<n;++j)


           if(d[i][k]+d[k][j]<d[i][j])


           {


             d[i][j]=d[i][k]+d[k][j];


             path[i][j]=path[k][j];


           }


}


void MGraph::shortestway(int u,int v)


{
int way[4];
int q=0;


int w=v;


while (w!=u)


{


      way[q++] = path[u][w];


      w=path[u][w];


}
cout<<u<<"到"<<v<<"最短路径为:";

--q;


for (int j=q; j>=0; j--)


      cout<<way[j]<<" ->";


cout<<v<<endl;


}


int main()


{


    MGraph g(4);


    g.Floyd();


    g.shortestway(2,3);


    system("pause");


    return 0;


}




0 0
原创粉丝点击