【坚持不能偷懒】
——好吧,已经偷懒很久了……
——M边数、N点数
关于SPFA的一些想法:
SPFA实际上是一种看脸迭代法
在SPFA过程中,一旦出现某个在真实最短路上出现过的点
因为它的权值已经达到了最优,所以在以后的过程中,不会再次出现
——关于Dij的heap优化——
DIJ的heap优化,每次均以最优来迭代,但消耗了寻找最优的时间(logN)
Dij的操作有两个 1、删除最优权值 2、给结点降权
常规的堆优化 操作1和2的复杂度均为logN
而1需要N次,2需要M次 所以复杂度为 (N+M)logN
假设每次对一条边权的查询,都会对一个点更新,则需要M次,所以MlogN
斐波那契堆 在对结点降权的操作中,其摊还复杂度为 O(1)
那么使用斐波那契堆的Dij,能优化到 NlogN + M * 1 的复杂度
————————————
而SPFA则看脸,以消除这个寻找最优的过程
每次遍历一遍队列的时间是M
但如果每次(次为遍历一遍队列的过程)寻找出的最优点均在队尾
且每次都会把剩余所有点标记flag
则达到最劣情况 N*M
举个例子:
把点记为 1 2 3 ... N
搜索 1 to N 的路径时
实际最优路是 1 - N-1 - N-2 - N-3 ... N
且 最优路径边权 均为 0
除最优边权外,其余边权为
1 —— 2^(N+K)
N - 1 —— 2^(N+K-1)
N - 2 —— 2^(N+K-2)
……
如此,每次搜索,队列中所有点flag均会置为1
但会搜索 N 次
——————一些优化的设想——————
1,SPFA不能保证搜索到目的点时,就已经最优
所以需要迭代至不能迭代为止
但当前获得的最短路,可以作为剪枝依据,若一个点的更新值劣于当前最短路
则忽略其影响
2,如果考虑针对如上情况,或许可以如同快速排序的选点,采取随机化策略
Ps:注意到SPFA中,产生的浪费操作为,当 A to B 更新后,A to B to C 也会更新
如此产生的影响,我也不知道怎么消除……
——————————————————
结点对之间的最短路
Johnson算法达到 O(NNlgN + MN)
来获取任意两点间最短路
如果图中无负权,则可以直接对每个点采用DijHeap来搜索
N * MlgN (斐波那契堆则为 NNlgN)
但如果图中出现的负权
仍然可以做出一定调整后采取相同策略
如果给每个点赋任意固定权重 h(i)
对于u,v两点,最短路权记为w(u,v)
记 W(u,v) = w(u,v) + h(u) - h(v)
那么 以W找出的最短路 和 原图最短路,一致
待续
——部分内容参考自《算法导论第3版》,推荐阅读原书