《SPFA算法的优化及应用》——姜碧野(学习笔记)

时间:2022-06-08 14:03:16

一、核心性质:三角不等式。最短路满足d[v]<=d[u]+w(u,v)

二、SPFA两种实现:

  常见的是基于bfs的,这是直接对bellman-ford用队列维护。根据最短路的长度最长为(n-1),以点入队n次判负环。适用于拓扑关系较强的环境。

  基于dfs的实现与前者本质相同。但实现了迭代的连续性,从而可以以搜到栈内的点来判正负环。但因迭代而导致耗时较多,易超时。

  精髓:只保存有用的状态。

三、求解最短路中两种实现方法的分析:

  bfs:某个点出队前可以被二次更新,从而使更优解替代次解,并用优解对其他值更新。

  dfs:构架形式灵活。不进行优化的情况下,次解会对其他值更新,浪费了时间。采用迭代加深,利用贪心初始解的原理,限制节点的递归深度并逐步放宽限制要求。此法在网格图上表现突出。

四、SPFA求最短路与判正(负)环的区别:(负环条件:沿环上路径可以使最短路不断减小;正环条件与之对应)

  求最短路即常见的bellman-ford的队列实现,之前又讨论了dfs实现。

  而在判环时,忽略其求最短路的作用,将dis[]初始化为0,并将全部点入队列(这里要注意,正是因为dis[]赋值为0,导致一些更新无法进行,所以要先把所有点入队)。已知存在正环,必然是由正边权引起的,那么沿环上路径一旦(d[u]+w(u,v))<0,d[v]<d[u]+w(u,v)不进行松弛。即初始化直接取边界状态,通过减少迭代次数优化算法。

五、判定正负环中两种实现方法的分析:

  bfs:1、以n次入队为判定条件,但可以在出队前进行二次更新,所以最多进行NM级更新,最大值=N*M*MaxEdge>maxlongint。借此提出:当dis[]>N*MaxEdge,可以判正环。(类比于入队n次)

    2、环构成了连通分量,那么缩点后去掉连通分量之间的边,不影响判正(负)环。

    3、牺牲程序正确性来判正(负)环。已知SPFA的平均运行时间为O(KM);而在存在环时,会因不断迭代使程序效率低下。借此提出:当程序效率低下时,存在正(负)环。表现形式为所有点入队总次数>T*(M+N),就判定存在,T一般取2,具体根据题目时限修改。分析:事实上,正是因为bfs迭代的不连续性,导致不能直接找到正环,退而求次,以n次入队判定。而n次入队其实包含了大量的冗余计算。

    注:前两条效果不明显,又以第二条代码实现复杂度高;而第三条,优化效果明显,却因为影响正确性,需灵活使用。

  dfs:正是在求解最短路中bfs的优势——二次更新,导致迭代不能连续进行,不可能找到同一个环上仍在队列中的节点。而dfs的劣势——连续迭代导致的时间复杂度较高,在判正负环时,却因对dis[]数组直接赋值0,而使效率大大提高。又因是连续迭代,很容易找到已标记的点,判定正负环。

六、小结

  求解最短路的常用形式:bfs。优化核心:用更优解代替次解进行迭代(或入队操作)。

  判定正负环的常用形式:dfs