Joern的华为软挑之路(二):SPFA算法

    xiaoxiao2021-03-25  151

     

    实际上我写这篇文章的时候我们的比赛之路已经结束了,无奈止步于64强之外,但是我们收获的东西却不少,在这里同各位分享一下我们做这个比赛的思路和遇到的歧路。

     

    一、Bellman - ford算法

    各位参与比赛的小伙伴都知道,费用流是解决这个问题的必不可少的一部分,在一开始我们并没有采用SPFA算法(大佬不要嘲笑),咱队的小伙伴对于算法这一块都是刚刚起步,通过网络我们首先搜索到了此算法。在这里简单介绍一下吧。

    适用条件&范围:

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

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

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

    差分约束系统;

    Bellman-Ford算法的流程如下:给定图G(V, E)(其中VE分别为图G的顶点集与边集),源点s数组Distant[i]记录从源点s到顶点i的路径长度,初始化数组Distant[n], 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到各顶点的最短路径长度。

    可知,Bellman-Ford算法寻找单源最短路径的时间复杂度为O(V*E).

    BellmanFord算法可以大致分为三个部分第一,初始化所有点。每一个点保存一个值,表示从原点到达这个点的距离,将原点的值设为0,其它的点的值设为无穷大(表示不可达)。第二,进行循环,循环下标为从1n1n等于图中点的个数)。在循环内部,遍历所有的边,进行松弛计算。第三,遍历途中所有的边(edgeuv)),判断是否存在这样情况:dv) > d (u) + w(u,v)则返回false,表示途中存在从源点可达的权为负的回路。 之所以需要第三部分的原因,是因为,如果存在从源点可达的权为负的回路。则 应为无法收敛而导致不能求出最短路径。 

     

    二、SPFA算法

    一开始我们并没有发现ford算法的不足,因为case规模较小,ford算法实现较简单,多少个点就进行多少次,每次都遍历所有边进行松弛操作(就是取当前的边到达点路径的最小值,到达的路径更小就更新),最后必然求得单源单汇的最短路径。但是我们忽视了他的效率,第二批case一出现就不行了。于是我们上网查找了SPFA算法,其实也就是Ford算法的队列优化。

    SPFA(Shortest Path Faster Algorithm) [图的存储方式为邻接表]是Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算。算法大致流程是用一个队列来进行维护。 初始时将源加入队列。 每次从队列中取出一个元素,并对所有与他相邻的点进行松弛,若某个相邻的点松弛成功,则将其入队。 直到队列为空时算法结束。它可以在O(kE)的时间复杂度内求出源点到其他所有点的最短路径,可以处理负边。SPFA在形式上和BFS非常类似,不同的是BFS中一个点出了队列就不可能重新进入队列,但是SPFA中一个点可能在出队列之后再次被放入队列,也就是一个点改进过其它的点之后,过了一段时间可能本

    身被改进,于是再次用来改进其它的点,这样反复迭代下去。判断有无负环:如果某个点进入队列的次数超过V次则存在负环(SPFA无法处理带负环的图)。

    SPFA算法有两个优化算法 SLF和 LLL:SLF:Small Label First策略,设要加入的节点是j,队首元素为i,若dist(j)<dist(i),则将j插入队首,否则插入队尾。LLL:Large Label Last 策略,设队首元素为i,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。引用网上资料,SLF可使速度提高 15 ~ 20%;SLF + LLL可提高约 50%。

     

     

     

    转载请注明原文地址: https://ju.6miu.com/read-13255.html

    最新回复(0)