Dijkstra算法和Floyd算法超详解以及区别

鉴于之前我看到过非常好的博客,如果自己总结的话,大多也是按照别的博主的思路来解释,所以就直接推荐给大家这些优秀的博客;
Dijkstra:最短路径dijkstra算法精品代码(超详解)
Floyd:Floyd 算法最短路径问题精品(超详解)

关于代码模板,我还是想展示自己的模板,毕竟自己的用着才是最舒服的(其实都大同小异,自己写一遍才能成为自己的东西)

Dijkstra模板:

#include 


using namespace std;
const int maxx=1e3+7;
#define INF 0x3f3f3f3f
int dist[maxx];
int c[maxx][maxx];
int s[maxx];
int v,e,n,m;
void init()
{
    memset(dist,INF,sizeof dist);//源点到所有点的最短距离初始为无穷大
    memset(c,INF,sizeof c);
    memset(s,0,sizeof s);
}
void dijkstra()
{
    for(int i=1;i<=n;i++) dist[i]=c[v][i];//找到与源点直接相连接的点,并且更新dist
    dist[v]=0;//源点到自己本身距离为0
    s[v]=1;//首先把源点标记
    for(int i=2;i<=n;i++)
    {
        int temp=INF;
        int u=v;
        for(int j=1;j<=n;j++)//找到与源点直接相连,并且距离最小的点
        {
            if(!s[j]&&dist[j]<temp)
            {
                u=j;
                temp=dist[j];
            }
        }
        s[u]=1;//将这个点标记(证明以后可以使用这个点作为中间点了)
        for(int j=1;j<=n;j++)
        {
            if(!s[j]&&c[u][j]<INF)//然后从u的周围找到一个直接相连并且没有使用过的点
            {
                int newdist=dist[u]+c[u][j];//然后判断使用这个点是否能使距离变小,是的话就更新
                if(newdist<dist[j])
                    dist[j]=newdist;
            }
        }
    }
}
int main()
{
    while(scanf("%d %d",&n,&m)&&n&&m)
    {
        init();//初始化数组;
        int x,y,t;
        for(int i=1;i<=m;i++)
            cin>>x>>y>>t,c[x][y]=t,c[y][x]=t;//存图

        v=1,e=n;
        dijkstra();
        cout <<dist[n]<<endl;
    }
    return 0;
}

带路径输出的Dijkstra
最短路径(dijkstra)以及输出路径
.
.
.

Floyd模板:

#include 
#include 
#include 

using namespace std;
#define INF 0x3f3f3f3f
const int maxx=1e3+7;
int G[maxx][maxx];//存图数组
int path[maxx][maxx];//path[i][j]记录从i到j经过了那个点过来的
int n,m;//分别表示定点个数和边的个数
void init()
{
    memset(G,INF,sizeof G);//初始化数组
    memset(path,-1,sizeof path);
    for(int i=0;i<maxx;i++)//到自己的距离为0
        G[i][i]=0;
}
void Floyd()
{                          //三重循环
    for(int k=1;k<=n;k++){ //选中的中间值 
        for(int i=1;i<=n;i++){ //数组横坐标
            for(int j=1;j<=n;j++){ //数组纵坐标 
                if(G[i][j]>G[i][k]+G[k][j]){    //如果以k中间点为中间点检测到路径更短 
                    G[i][j]=G[i][k]+G[k][j];    //更新路径值
                    path[i][j]=k;   //更新要经过的中间点 
                }
            }
        }
    }
}
int main()
{
    while(scanf("%d %d",&n,&m)&&n&&m)
    {
        init();//初始化
        int x,y,z;
        for(int i=0;i<m;i++)
        {
            scanf("%d %d %d",&x,&y,&z);
            G[x][y]=z,G[y][x]=z;
        }
        Floyd();
        printf("%d\n",G[1][n]);//输出点1到点n的最短距离
    }
    return 0;
}

.

带路径输出的Floyd只需要添加一个自己写的函数即可:

void ptf(int u,int v)
{
    cout <<u<<"->";
    while(path[u][v]!=-1)
    {
        u=path[u][v];
        cout <<u<<"->";
    }
    cout <<v<<endl;
}

.
.
.

Dijkstra算法和Floyd算法的区别之处:

Dijkstra算法和Floyd算法对比分析

总结来说就是

1.

Dijkstra不能处理负权图,Flyod能处理负权图;

2.

Dijkstra处理单源最短路径
Flyod是处理多源最短路径
这个区别有个博主写的特别好,生动又形象,来吧!传送门:最短路径——Dijkstra算法和Floyd算法

3.

Dijkstra时间复杂度为O(n^2)
Flyod时间复杂度为O(n^3) 空间复杂度为O(n ^ 2);
所以题目中如果是单源点正权图,就用Dijkstra
如果是任意两个点之间的最短路径或者是负权图,就用Floyd;

你可能感兴趣的:(最短路径,基础算法——图论)