最短路

最短路问题包括:单源最短路、每两点最短路。

一、单源最短路:Dijkstra算法、Bellman-Ford算法、SPFA算法

    1、Dijkstra算法 --- 只能处理正边权图

        (1) 原始Dijkstra算法:O(n^2)。

        (2) 使用优先队列优化的Dijkstra算法:O(E*logE):

            想象成从源点有一水柱喷涌而出,水流经过若干条带权的边后(权值越大,流经时间越长),整张地图分成有水部分和无水部分,从有水部分中选取一个距离源点最短的点(当然这个点需要从来没有被选取过),以这个点为中心,水流又流向其它无水部分节点,如此不断更新地图。这里的“从有水部分中选取一个距离源点最短的点”需要用到优先队列。

    2、Bellman-Ford算法:O(VE)  ---  优点:可以处理负边权图

        负环定义:一个环路中所有路径的权值之和为负,称为负环。

        伪代码 Start

            (初始化)起点距离:0,其他点距离:INF // 不能太大,防止溢出

            for n = [1 ~ N) //最多做n-1次,如果做了n-1次之后还有点的距离没更新,那么说明图存在负环。

                for e = [1 ~ E] 

                    d[e.v] = min ( d[e.v]  ,  d[e.u] + cost[e] ) //称为松弛操作

            for e = [1 ~ E] 

                if ( d[e.v] > d[e.u] + cost[e] )  return false; //存在负环

            return true; //不存在负环 

        伪代码 End

3、SPFA算法:O(kE) --- 基于Bellman-Ford算法优化,可以处理负边图,并且复杂度较小

用一个先进先出的队列维护,先计算每个点的估计距离,如果发现这个值能再次更新,那么把它重新加入队列,以便检查它相邻的点。

    伪代码 Start

        (1)(初始化)起点距离:0,其他点距离:INF,新建队列que:推入起点。 
        (2) 从队首取出top,标记top已出队(负环检查:同时对top出队次数进行检查,如果大于n,说明出现负环,算法结束)。遍历top所连的边e,如果e.to可以更新,那么更新e.to,检查e.to是否在队列中,如果不在加入队列中。

        (3) 重复步骤2,直到队列为空。

    伪代码 End

 

二、每两点最短路:Floyd算法  --- 图可以是有向图或者无向图,可以存在负边,但是不能存在负环。

    伪代码 Start

        (初始化)d[i][i]:0,其他两点间距离:INF //不能太大,防止下文 d[i][k] + d[k][j] 溢出

            for k = [0,n)

                for i = [0,n)

                    for j = [0,n)

                        d[i][j] = min( d[i][j] , d[i][k] + d[k][j] ); //可以加个pre数组,同时记录路径。

    伪代码 End

Floyd算法中边权可正可负,只要图中不存在负环都可以得出正确答案。关于Floyd算法的负环判定,见:Floyd求最小环,只要求出的最小环是正的,就不存在负环。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值