最短路

本文介绍4种算法:SPFA, Dijkstra, Bellman-Ford, Floyd
PS:文中分大小写。 图为G(V,E),V为节点集合,E为边集合,但v表示某个节点(v∈V)

Dijkstra:

  • 原理:通过每一次解压节点min{key[v]|v∈G-已经生成的最短路径的树}并添加到树中,并将所有以v为起点的边松弛(key域),来达到最短路(贪心)
  • 注意:图中不能有负权,不能查是否有负权回路
  • 步骤:
    1. 初始化key域。每个key[v]=INF,v∈V
    2. 将最短路起点S的key[S] = 0
    3. 定义一个优先队列 priority_queue (#include <queue>) ,并将S节点(可以考虑用pair来绑定key域,也可以用一个结构来绑定)压入。//STL的队列默认为最大优先,故要创建一个比较类,重载()来实现最小堆
    4. 循环(直到队列为空)每一次解压最小值, 将最小key域所绑定的节点v解压出来并添加到树中(直接用一个bool数组来确定是否在树中即可,要输出路径就定义一个父亲域并维护)将v为起点的边全部松弛一遍,维护key域。并将这条边的终点压入队列。
  • 分析:时间复杂度O(N^2)
  • 适用于:稠密图
  • 优化:优化堆的实现,即手打FIB堆或其它比STL快的堆= =。可以达到O(NlogN)

Bellman-Ford:

  • 原理:通过V-1次(最短路长度最多有V-1条边嘛- -)对每一条边松弛,来实现最短路(同样是贪心)
  • 好处:图中可以有负权,也能判断是否有负权回路
  • 步骤:
    1. 初始化key域。每个key[v]=INF,v∈V
    2. 循环(1~n-1)
    3. 枚举所有边进行松弛
    4. 判断是否有回路,循环(1~V)
      如果以v∈V为起点的边还能松弛,即有回路。(自己拿算导看证明哈,或者谷歌百度,或者自己想)
  • 分析:时间复杂度O(VE)
  • 适用于:稀疏图和负权图
  • 优化:我布吉岛

Floyd:

4行代码:

for(k = 1; k <= N; k++)
	for(i = 1; i <= N; i++)
		for(j = 1; j <= N; j++)
			node[i][j] = min(node[i][j], node[i][k]+node[k][j]);

SPFA:(全名为:ShortestPathFasterAlgorithm)

百科

看到好文章,直接转过来了(点击打开链接

我们知道,求一个图中的单源最短路径有Dijkstra、Ford这两种经典的算法。其复杂度均是O(N2),通过堆的优化,Dijkstra可以达到O(NlogN)的复杂度。但对于一些十分稀疏的图,这个复杂度就有些浪费了。当一个图中的边数e远远小于N2时,我们就考虑是否有一种算法,其时间复杂度只跟边数e有关系。于是SPFA诞生了。

我们知道,Dijkstra的O(N2)是因为又一重循环是为了找到目前的Dist值最小的节点,于是我们想,能不能不找最小的,只是按照一定的顺序更新就可以了。那么算法的雏形就出来了,设S为源点:

Quene←S
While Quene not empty do
    Tmp←Quene
    For each node i with an edge to Tmp do
        If Dist[i] > Dist[Tmp]+length(edge(i,Tmp)) then
            Dist[i]←Dist[Tmp]+length(edge(i,Tmp))
            If i not in the Quene then
                Quene←i

这就是传说中的SPFA。我们来看看它的执行过程:

为了图片的美观,我隐藏了顶点的标号。左上角的顶点为源点,黄的的点表示在队列中,绿色的点表示正在处理:

至此,队列空,算法结束。

为什么它能收敛呢?为什么它不会一直循环下去呢?因为总有一刻Dist[i]已经达到最小值,这时i这个顶点就再也不会入队了,并且当访问到i的时候,与i邻接的顶点也会被更新。所以总有一刻,所有的Dist都是最优值,算法结束。

可以证明,假设每个节点的平均入队次数是k,那么时间复杂度就是O(ke)。而这里的k几乎可以认为是一个常数,所以简算之后时间复杂度为O(e)。

如果时间复杂度优于这个值,就是说我们并没有处理完图中所有的边,就不可能一定可以得到最优解,所以,O(e)是所期望的最好的复杂度。
PS:  有可能会更新,,欢迎大家吐槽

发布了40 篇原创文章 · 获赞 2 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章