今天做最短路问题有感~
发现以前理解的dijkstra还是有一定偏差,
蒟蒻献上本篇博客希望进一步巩固一下算法,如果能帮到大家更好了QAQ
(希望大家顺手可以给个赞QAQ 非常感谢QAQ)
首先:
dijkstra是用于解决单源最短路上无负权边的算法~
使用邻接表的dijkstra其时间复杂度为O(V*V)(vertex*edge)
而二叉堆优化的dijkstra(注意是单源!)时间复杂度可以有O((V+E)logV)
当然其实也可以对多个点都用一次dijkstra算法,它就可以变成多源最短路算法,但我们一般不会这么做~
原因在于即使经过堆优化,每个点都乱搞来一次dijkstra,其时间复杂度会到O(V(V+E)logV)
那其实还不如用一次Floyd算法(多源最短路),只需要O(V*V),就可以达到我们想要的效果了~
比较重要的一点是:
dijkstra在更新最优解时(未更新完时),并不能保证与源点距离最短的点到终点的距离一定是最优解。
感觉其实整个过程还是比较像搜索~,只是当前贪心引入可达点后,并不会再从该点出发,走向其他点。也就达到了每个点只走一次的效果QAQ
有点类似Bellman-Ford算法,我们也叫它已死的 SPFA
当前dijkstra从1出发,到4
首先dijkstra会更新源点到点2的距离
]
然后更新源点到点3的距离
接下来,dijkstra会贪心的更新与源点最近的点(此时为点2),到其他点的距离。
如图所示,会更新点2->4
]
但此时引入点4,但因为点4出度为0,因此我们无法引入点4到其他点的路径。可1->4并不是最优解,只是可行解之一。
我们根据dijkstra算法,仍然要更新3->4的距离
]
此时遍历完毕~
C++板子:
#include<bits/stdc++.h>
#define For(i,m,n) for(register int i=m;i<n;i++)
#define rFor(i,m,n) for(register int i=m;i>n;i--)
#define r(a) read(a)
#define rr(a,b) read(a),read(b)
#define rrr(a,b,c) read(a),read(b),read(c)
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
template <class T>
inline void read(T &x)
{
x=0;
T f=1;
char ch