假设我有一个有向图G(V,E)在其边缘上具有积分正权重。如果我知道对于每个边缘e∈E weight(e)∈{0,1,.. 2 ^ W} (其中W相对较小)如何在O((V + E)* W)中实现dijsktra的算法?
我尝试修改Dial的算法,如果weight(e)∈{0,1,..,W},我可以使用存储桶并在O(V * W + E)中实现dijsktra,但我似乎做不到结果。
答案 0 :(得分:0)
当我必须实现Dijkstra的算法时,通常使用二进制堆,而无需 reduce_key操作。
为此,您将(cost,vertex)记录放入堆中,并且每当一个顶点的成本下降时,您只需放入一个新的。当您从堆中弹出一个顶点时,如果已经完成,则可以忽略它。无论如何,您都必须跟踪完成了哪些顶点,这很容易。
这会占用更多空间,但是复杂度仍然为O(| E | log V)(与O(| V + E | log | V |相同)或O(| E | log | E | ),算法将遍历的连接组件)
现在是log | E |的因数上面的事实来自于| E |堆中的元素。如果将具有相同优先级的所有元素分组到列表中并将这些列表放入优先级队列,则该日志| E |因素变成对数(不同优先级的数量)。注意,堆数组不再是优先级队列的合适结构,但是各种有序树都可以正常工作。当您不需要reduce_key时很容易。
在您的情况下,优先级队列前端的顶点之间的成本差异与优先级队列中最高成本的差异最大为2 ^ W。这意味着队列中最多有2 ^ W个不同的优先级,使用这种优先级队列的Dijkstra算法的复杂度为O(| E | W)。
由于您不想分配2 ^ W个存储桶,因此链表的Patricia树将为您的案例提供一个可行的优先级队列。