【POJ/算法】 3259 Wormholes(Bellman-Ford算法, SPFA ,FLoyd算法)

本文介绍了Bellman-Ford算法,包括其优缺点、步骤和负环检测。SPFA是Bellman-Ford的队列优化版,提高了效率。同时,文章讨论了如何利用这些算法解决POJ 3259 Wormholes问题,该问题涉及时间旅行和虫洞,需要判断是否能通过路径回到起点的过去时间。
摘要由CSDN通过智能技术生成

Bellman-Ford算法

Bellman-Ford算法的优点是可以发现负圈,缺点是时间复杂度比Dijkstra算法高。而SPFA算法是使用队列优化的Bellman-Ford版本,其在时间复杂度和编程难度上都比其他算法有优势。

Bellman-Ford算法流程分为三个阶段:

  • 第一步:数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n]为INF, Distant[s]为0;

  • 第二步:以下操作循环执行至多n-1次,n为顶点数: 对于每一条边e(u, v),如果Distant[u] + w(u, v) < Distant[v],则另Distant[v] = Distant[u]+w(u, v)。w(u, v)为边e(u,v)的权值; 若上述操作没有对Distant进行更新,说明最短路径已经查找完毕,或者部分点不可达,跳出循环。否则执行下次循环;

  • 第三步:为了检测图中是否存在负环路,即权值之和小于0的环路。对于每一条边e(u, v),如果存在Distant[u] + w(u, v) < Distant[v]的边,则图中存在负环路,即是说改图无法求出单源最短路径。否则数组Distant[n]中记录的就是源点s到各顶点的最短路径长度。

v的最短距离保存在 d[v]中。

在这个算法中,需要了解的几点

1、只有上一次迭代中松驰过的点才有可能参与下一次迭代的松弛操作。

似乎算法在遍历每一条边的做法会浪费时间,或许我们只需要考虑那些被成功松弛的点的邻点就可以了。我们可以用一个队列来维护这些被成功松弛的点,这个小小的改进可以节省很多时间,改进后的算法叫做SPFA

2、迭代的实际意义:每一次迭代k中,我们找到了经历了k条边的最短路

3、没有点能够松弛时,迭代结束

Bellman-Ford(G,w,s) :boolean   //图G ,边集 函数 w ,s为源点
 
        for each vertex v ∈ V(G) do        //初始化 1阶段
 
            d[v] ←+∞
 
        d[s] ←0;                             //1阶段结束
 
        for i=1 to |v|-1 do               //2阶段开始,双重循环。
 
           for each edge(u,v) ∈E(G) do //边集数组要用到,穷举每条边。
 
              If d[v]> d[u]+ w(u,v) then      //松弛判断
 
                 d[v]=d[u]+w(u,v)               //松弛操作   2阶段结束
 
        for each edge(u,v) ∈E(G) do
 
            If d[v]> d[u]+ w(u,v) then
 
            Exit false
 
    Exit true

SPFA

算法特点:在 Bellman-ford 算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。 

关键词:初始化,relax,队列

实现的过程和Bellman_Ford类似

【初始化】

dis数组全部赋值为INF,pre数组全部赋值为-1(表示还不知道前驱),

dis[s] = 0 表示源点不要求最短路径(或者最短路径就是0)。

【队列+松弛操作】

读取队头顶点u,并将队头顶点u出队(记得消除标记);将与点u相连的所有点v进行松弛操作,如果能更新估计值(即令d[v]变小),那么就更新,另外,如果点

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值