卡spfa的一些方法&&对spfa的一些深入理解
知己知彼,百战不殆
spfa队头元素不一定是队内最优最应该先出队的元素,出队顺序全看入队顺序。
整理了一些常见的卡spfa方法及见招拆招的针对性优化。
卡spfa的关键依据:贪心的松弛操作、每次更新节点时更新所有出边,(偶尔)负权边
核心:诱导贪心的spfa不断更新次短路,多次更新与该点相连的部分。
常见卡spfa用图(可以在所有普通图上外挂,加以诱导节点;甚至互相搭配):
链套菊花图(链上负权边,会多次更新非链的菊花图的另一半)、网格图(竖边权为0或很小(万恶之源),使很多长度不同的路径权值和相近,那么一次找到最短路的概率就小得多,就有可能多找了几条次短路,多更新了几次同一个点)
见招拆招:
1、随机取点:每次从队列取队头前,先把队头与队内随机一个元素交换(数组模拟队列会非常方便这种操作);
2、随机出边:当前点出队时,将出边暂存,以随机顺序访问;
(1 2 有效克制菊花图)
……
如何看待 SPFA 算法已死这种说法? - fstqwq 的回答 - 知乎
如何卡spfa? - Raffica的回答 - 知乎 https://www.zhihu.com/question/268382638/answer/337778164
给spfa加堆优化:时间复杂度O(kMlogM) 点u入堆时要注意不管u在不在堆里,都要入堆;或实现堆内元素修改操作(先删了队里的u再入堆加上当前的u),这样logM能变logN,但常数更大。可能在很个别的时候会用到。
后记:
(段凡丁曾经证明 SPFASPFA 的时间复杂度是 O(ke)O(ke)(kk 是小常数),但是他的证明已经被证明是错误的,请大家注意)