【DayDayUp】【算法_图_最短路_之一_Dijkstra和几种优化姿势】

【坚持不能偷懒】

V 定点数 E 边数

【原生DIJ】

从初始点出发 V 次循环

每次对当前点扩展【有效边】 (如果直接对所有点刷 是 V ,而用链表刷有效边是总计为E ) 

更新已知最短路  

再取出【权值最低点】作为新点重复 (寻最小值 V )

故复杂度为  V * V  + E

【DIJ 的 Heap 优化】

考虑到每次找【权值最低点】这一步,对其进行堆优化

其具体措施是

写一个堆

然后每次有点扩展【有效边】时,【改变了权值】,则更新堆

这样,每次【更新堆】是一个Log V 的复杂度

点的进入必然会引起更新

每条边的刷新 也都可能引起更新

所以最坏需要 E + V 次更新

故复杂度为 ( E + V )* Log V

—————————————PS———————————————

有人似乎直接用头文件自带的【优先队列】来优化DIJ

我读了其中两则代码,发现他们是用

【优先队列存下标】

【对应数组存当前最小值】

每次新进则PUSH。

BUT,直接更新数组的话,优先队列是不会更新的

我试着写了一个【优先队列存下标,对应数组值变动,然后改掉数组内的值,PUSH新数】的小测试

发现【不能在PUSH后正确更新】

【如果改动之后还能正确更新的话,不就是一个排序的 N Log N 的过程的了么……】

用优先队列直接优化DIJ 很明显是在逗宝宝……

—————————————PPS————————————————

2017.3.16

哈,前几天和大祥子提到这,发现我理解错了,用优先队列也是可以搞的

不过上面那种搞法确实是错的

用优先队列搞

就是每次更新,就在优先队列里直接加入这个新的值

然后优先队列Pop出一个被改过的值,就Pass掉

这样会让优先队列变大,比堆效率差点,需要的空间多些,但还是可以搞的

具体怎么Pass,譬如优先队列里存(点,权)

然后再开个数组记录(点,权)

每个点的权保持最小,如果Pop出的权比数组里的大,说明是无效的,就Pass掉。

【SPFA】

首先这个算法的名字有槽点…… 据说歪果仁不这么叫……

SPFA能处理 无负环的所有问题

SPFA的过程是

用一个队列维护【被更新的点】

然后从队头开始刷刷刷

如果更新了队内的点,不管

如果更新了队外的点,加进来


有些不明所以不明觉厉的博客告诉我们,这个基本跑两回以内就能刷出结果

即复杂度为 K * E 

而 K 是一个小的常数……

麻辣个鸡蛋的……

这很明显是在逗我…… 要这样还怎么被各种卡……

同普通DIJ,最坏还是可以刷 V 回 的,然后就炸了

故复杂度为 V * E ( 不被卡可视为  E )


三个分别是

【原生DIJ】  V * V  + E (稳定的复杂度)

【DIJ 的 Heap 优化】 ( E + V )* Log V (E为更新次数,通常不会达到

理想情况 VlogV——针对稠密图

最劣恶化 V * V * Log V——特殊完全图

【SPFA】V * E(V为更新次数,通常不会达到)

理想情况E —— 针对稀疏图

最劣情况V * V * V—— 特殊完全图



你可能感兴趣的:(算法_图)