最短路径的SPFA算法

    最短路径有三种比较普遍的算法

    1.bellman_ford可以计算带有负权值的单源最短路径,并且可以判断是否存在最短路径;

    2.dij可以非常快速的计算正权值的单源最短路径(最好加上heap优化)

    3.floyd可以快速计算点对之间的最短路径(基本可以说是非常好写又非常快速的,其他单源算法用于点对间都比较慢)

 

    还有一种算法,是昨天我在搞ZOJ1857时接触到的,SPFA,可以说是非常迅速的算法了..比Dij+Heap快了好几个数量级(SPFA大概60ms,而Dij至少300ms)

 

    SPFA其实是类似bellman_ford算法,bellman_ford的依据是如果有最短路径,那么将所有边(E)松弛V-1次之后,必然得到其最短路径(因为最短路径最长为V-1个边的和),而在松弛的时候,通常利用flag标识该次是否松弛过从而可以快速跳出进行优化.

 

    但可惜的是,bellman_ford通常都会将全部边都进行松弛,甚至有的边根本不需要,也要进行多余的判断,为了解决这个问题,我们引入了队列,将所有需要松弛的点入队,仅仅松弛队列中的点,因此能很快的得到最短路径

 

    可以入队的点:

    1.源点.源点是最初我们手工入队的点,注意,此处应该把所有的源点全部入队,否则会产生有些点无法到达导致的错误情况

    2.经过松弛的点.如果一个点经过了松弛,那么该点的临点都有可能需要进行松弛,所以必须将该点入队进行随后判断

 

    SPFA的具体算法:

    1.初始化队列,所有源点入队

    2.如果队列为空,那么计算完毕(END)

    3.否则,取队首元素,判断其邻接点是否需要松弛

    4.需要松弛的话,则进行松弛,并对该点松弛次数+1,如果次数大于V-1,跳出,表明不存在最短路径(END)

    5.否则,判断该邻接点是否在队列中,如果不在,则入队,继续取邻接点

    6.邻接点全部取完,跳至步骤2

 

    SPFA的优化有两个,SLF(Smallest Label First)比较好实现,当入队时比较入队点和队首元素大小,如果小,则从队首入队,否则正常入队

 

具体代码如下:

 

上述代码是从ZOJ1857中弄来的,可以看到,对于多个源点来讲,必须都事先入队.另,used是用来判断是否在队列中的.

 

SPFA有一个非常厉害的独特利用之处,就是类似本题的多源点最短路径,非常实用..可以借鉴(我错了..其实dij他们都可以的..)

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值