全源最短路问题–Floyd算法

Floyd算法,也就是弗洛伊德算法,用来解决全源最短路问题。就是对给定的图G,求任意两点u,v之间的最短路径长度,时间复杂度为O(n^3)

由于n^3的复杂度决定了顶点数n的限制约在200以内,因此使用邻接矩阵来实现Floyd算法是非常合适且方便的。

Floyd算法基于一个事实
如果存在顶点k,使得以k作为中介点时,顶点i和顶点j的当前最短距离缩短,则使用顶点k作为顶点i和顶点j的中介点,即
dis[i][k] +dis[k][j] < dis[i][j] 时,令

dis[i][j] = dis[i][k] +dis[k][j]
其中dis[i][j]表示从顶点i到顶点j的最短距离。

//基于上面的事实,Floyd算法的模板流程如下:

枚举顶点 k 属于 [1,n]
    以顶点 k 作为中介点,枚举所有顶点对 i 和 j (i 属于 [1,n], j 属于 [1,n]) 
        如果 dis[i][k] + dis[k][j] < dis[i][j] 成立
            赋值 dis[i][j] =  dis[i][k]+dis[k][j] 





//Floyd算法程序具体实现

#include <cstdio>
#include <algorithm>

using namespace std;



const int INF=0x3fffffff;

const int MAXV=200;

//n为顶点数,m为边数 
int n,m;

//dis[i][j] 表示顶点i和顶点j之间的最短距离 
int dis[MAXV][MAXV];


void Floyd()
{

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

            for(int j=0;j<n;j++)
            {
                if( dis[i][k] != INF && dis[k][j]!=INF 
                    && dis[i][k]+dis[k][j]<dis[i][j]  )
                {

                    //找到更短的路径
                    dis[i][j] = dis[i][k] + dis[k][j];


                }

            }

        }


    }




}



int main()
{

    int u,v,w;

    //dis数组赋初值 
    fill( dis[0],dis[0]+MAXV*MAXV,INF  );

    //顶点数n,边数m 
    scanf("%d%d",&n,&m);

    for(int i=0;i<m;i++)
    {
        scanf("%d%d%d",&u,&v,&w);

        //以有向图为例进行输入 
        dis[u][v]=w;



    }


    Floyd();

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

            printf("%d",dis[i][j]);

        }

        printf("\n");

    }




}
















注意点

对于Floyd算法来说,不能将程序中的最外层的k循环放到内层。
也就是不能产生i->j->k的三重循环,这会导致出错。

出错原因

如果当较后访问的dis[u][v]有了优化之后,
前面访问的dis[i][j]会因为已经被访问而无法获得进一步的优化。