问题描述
在一个问题中,我得到一个图 G,它只有 正权重 和它的 直径(即 G 中每对顶点之间的最大最短路径) = D. 该问题要求单源最短路径算法,该算法比 Dijkstra 更快,并在 O(V+E+D) 时间内运行。
到目前为止我所考虑的: 曾经想过添加哑节点的方法,将G转化为未加权的图G',然后运行BFS,但是这样会导致复杂度为:O(V+WE)
(如在 G' 中,E' = O(WE) 和 V = O(WE+V))
在我看来,D 并没有真正帮助降低问题的复杂性,因为权重的总和(即要添加的虚拟节点的总数)与 D 无关。
解决方法
将 Djikstra 算法与优先队列的优化版本一起使用。假设图有节点 0..V-1
。
优先级队列将由节点的双向链表的数组 Arr[0..D]
(索引介于 0 和 D
之间的数组)组成,以及索引 i
表示数组中所有节点的优先级与起始节点的距离至少为i
,并且是一个数组location[0..V - 1]
,其中location[node]
的值为{中的双向链表节点{1}} 包含 Arr
,如果没有这样的节点,则为 node
。当我们找到从起始节点到相关节点的长度为 null
的路径时,我们将一个节点存储在列表 Arr[i]
中。
将一个不存在的节点加入优先级队列是i
- 如果我们有一个暂定距离O(1)
,那么我们将该节点加入链表s
并更新Arr[s]
相应地。请注意,如果优先级为 location[node]
,我们实际上应该避免将节点完全添加到优先级队列中,并确信我们稍后会将其添加到优先级为 >D
的队列中。
从优先队列中删除给定节点也是<= D
- 我们可以使用O(1)
在O(1)
中找到它的双链表节点,从双链表中删除该节点-list,并将 location[node]
设置为 location[node]
。当我们改变一个节点的优先级时,我们将需要这个操作。
查找和删除最小节点不那么简单。我们不断地增加 null
直到我们找到一些 i
使得 i
不为空。然后我们从优先级队列中删除在 Arr[i]
中找到的节点(不要忘记更新 Arr[i]
)。在整个程序中完成的增量总数为 location[node]
,因为我们将一次将 D
从 i
更改为 0
。忽略增量,此过程中完成的其他工作是D
。
请注意,这仅是有效的,因为我们可以保证,一旦删除优先级为 O(1)
的节点,我们将永远不会将另一个优先级为 i
的节点添加到优先级队列中。这也只是因为我们知道我们永远无法真正删除添加到具有优先级 <i
的优先级队列中的任何内容,因为我们只能在其最终确定的正确路径长度为 {{} 时从优先级队列中删除某些内容1}} - 因此,没有必要将任何内容添加到优先级为 > D
的优先级队列中。这是根据 Dijkstra 算法在图具有正边权重时的一般性质以及图的直径为 <= D
的事实得出的。
因此算法将是 > D
,根据需要。