每一对顶点之间的最短路径【Floyd】

算法总结:

①Dijkstra算法用的是贪心策略,每次都找当前最短路径的下一个最短距离点。所以不适合带有负权的情况。至于时间效率通过各种优化可以到达不同的程度。但是朴素的Dijkstra算法永远是最稳定的。

②Bellman-Ford算法是Dijkstra的一种变式,它摒弃了贪心的策略,但是每次都需要松弛所有的路径,所以也适合负权的情况。但是时间效率较低。有资料显示,Bellman-Ford算法也可以应用贪心策略,这属于高级技巧,这里不予考虑。

③Floyd算法用的是动态规划的思想,由于是不定源点,所以它需要对所有的情况进行松弛操作,最终获得所有的最短路径长度。由于需要遍历,所以它的时间效率比较低。但是遍历策略好的话,还是能很快得到想要的结果。

SPFA算法是用FIFO队列优化的Bellman-Ford算法,所以支持负权的情况,由于已经将需要考虑的节点放入队列中,所以避免了很多不必要的松弛,时间效率也相对较高。由于队列中无法进行修改,所以时间效率相对不稳定。

⑤所有的队列优化其实都能转化为hash优化,这里不再考虑更进一步的优化。

 

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一、Dijkstra算法:单源到所有节点的最短路算法。


算法要求:可以是无向图或有向图,所有边权均为正,最短路存在。如果图是五环图,则最长路也一定存在,但是如果是有环图,则最长路不一定存在。

算法思想:每次比较所有的从源点可以到达的路的长度,然后选出最短的一条放入源点集合,然后更新最短路径长度。这样,当所有的点都在源点集合中时,得到的长度就是最短路长度。

1)使用邻接矩阵的稠密图普通Dijkstra算法

         算法时间复杂度:O(n^2)

         算法代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define INF (1<<31)-1   //int最大值
#define MAXN 100   //最大节点数
int dist[MAXN],c[MAXN][MAXN];
//dist[i]存放从源点到i节点的最短距离,c数组用来表示图
int n,line;   //n为节点数,line为边数

//迪杰斯特拉算法主算法模块
void Dijkstra(int v)   //v代表源点
{
    inti,j,temp,u;  //temp用于暂时存放最短路径长度
    boolvis[MAXN];   //判定重复标记数组
    for(i=0; i<n; i++) //dist数组与vis数组的初始化
    {
        dist[i]=c[v][i];
        vis[i]=0;
    }
    dist[v]=0;  //源点到源点的距离设为0
    vis[v]=1;   //源点默认为已经访问
    for(i=0; i<n; i++) //总共应该遍历n次
    {
        temp=INF;  //初始化temp为最大值
        u=v;   //初始化最短节点为当前节点
        for(j=0; j<n; j++)if((!vis[j])&&dist[j]<temp)
            {
                u=j;   //找出v距离最短的节点u
                temp=dist[j];   //更新最短距离
            }
        if(temp==INF)return;   //不存在其它节点了,返回
        vis[u]=1;   //标记该最短节点为已经访问
        for(j=0; j<n; j++)if((!vis[j])&&dist[u]+c[u][v]<dist[j]) //松弛操作
                dist[j]=dist[u]+c[u][v];  //更新最短距离
    }
}
int main()
{
    int p,q,len,i,j,origin;
    while(scanf(“%d%d”,&n,&line))
    {
        if(!n&&!line) break;  //如果图为空白图,则结束
        for(i=0; i<n; i++)
            for(j=0; j<n; j++)
                c[i][j]=INF;   //初始化节点间距离,默认为节点间全部不连通
        while(line--)   //输入这line条边的内容
        {
            scanf(“%d%d%d”,&p,&q,&len);
//p为边的起点,q为边的终点,len为边的长度
            //下面是无向图的输入方式
            if(len<c[p][q])
            {
                c[p][q]=len;
                c[q][p]=len;
            }
            /*下面是有向图的输入方式
            if(len<c[p][q])
                   c[p][q]=lem;
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值