最短路径相关算法和试题

一、Bellman-Ford算法

最优性原理

 

它是最优性原理的直接应用,算法基于以下事实:

l          如果最短路存在,则每个顶点最多经过一次,因此不超过n-1条边;

l          长度为k的路由长度为k-1的路加一条边得到;

l          由最优性原理,只需依次考虑长度为1,2,…,k-1的最短路。

适用条件&范围

l          单源最短路径(从源点s到其它所有顶点v);

l          有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图);

l          边权可正可负(如有负权回路输出错误提示);

l          差分约束系统(需要首先构造约束图,构造不等式时>=表示求最小值, 作为最长路,<=表示求最大值, 作为最短路。<=构图时, 有负环说明无解;求不出最短路(为Inf)为任意解。>=构图时类似)。  

算法描述

l          对每条边进行|V|-1次Relax操作;

l          如果存在(u,v)∈E使得dis[u]+w<dis[v],则存在负权回路;否则dis[v]即为s到v的最短距离,pre[v]为前驱。  

时空复杂度                                                                                            

for i:=1 to |V|-1 do

    for 每条边(u,v)∈E do   Relax(u,v,w);

for每条边(u,v)∈E do

if dis[u]+w<dis[v] Then Exit(False)

算法时间复杂度O(VE)。因为算法简单,适用范围又广,虽然复杂度稍高,仍不失为一个很实用的算法。

改进和优化   如果循环n-1次以前已经发现不存在紧边则可以立即终止; Yen氏改进(不降低渐进复杂度);SPFA算法

 

题目:poj3259  http://poj.org/problem?id=3259 代码如下:

二、             SPFA算法

算法简介

SPFA(Shortest Path Faster Algorithm)是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。 它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边。

算法流程

SPFA对Bellman-Ford算法优化的关键之处在于意识到:只有那些在前一遍松弛中改变了距离估计值的点,才可能引起他们的邻接点的距离估计值的改变。因此,算法大致流程是用一个队列来进行维护,即用一个先进先出的队列来存放被成功松弛的顶点。初始时,源点s入队。当队列不为空时,取出队首顶点,对它的邻接点进行松弛。如果某个邻接点松弛成功,且该邻接点不在队列中,则将其入队。经过有限次的松弛操作后,队列将为空,算法结束。SPFA算法的实现,需要用到一个先进先出的队列 queue 和一个指示顶点是否在队列中的标记数组mark。为了方便查找某个顶点的邻接点,图采用临界表存储。

算法代码

Procedure SPFA;

Begin

             initialize-single-source(G,s);

             initialize-queue(Q);

             enqueue(Q,s);

             while not empty(Q) do begin

                u:=dequeue(Q);

                for each v∈adj[u] do begin

                   tmp:=d[v]; relax(u,v);

                   if (tmp<>d[v]) and (not v in Q) then enqueue(v);

                   end;

                end;

End;

负环处理

   需要特别注意的是:仅当图不存在负权回路时,SPFA能正常工作。如果图存在负权回路,由于负权回路上的顶点无法收敛,总有顶点在入队和出队往返,队列无法为空,这种情况下SPFA无法正常结束。

判断负权回路的方案很多,世间流传最广、比较容易实现并且高效的方法的是记录每个结点进队次数,超过|V|次表示有负权。

题目:POJ 1062 http://poj.org/problem?id=1062 代码如下:

 

 

 

三、Floyd算法

 

题目:POJ 2253 http://poj.org/problem?id=2253 代码如下:

 

四、Dijkstra算法

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值