在Dijkstra's algorithm on Wikipedia (older version, now corrected by me)中,具有优先级队列的实施将在检查较短路径之前检查是否访问过vertex
。
真的有必要吗?甚至是正确的?
function Dijkstra(Graph, source):
dist[source] ← 0 // Initialization
for each vertex v in Graph:
if v ≠ source
dist[v] ← infinity // Unknown distance from source to v
prev[v] ← undefined // Predecessor of v
end if
Q.add_with_priority(v,dist[v])
end for
while Q is not empty: // The main loop
u ← Q.extract_min() // Remove and return best vertex
mark u as scanned
for each neighbor v of u:
if v is not yet scanned: // **is this in need?**
alt = dist[u] + length(u, v)
if alt < dist[v]
dist[v] ← alt
prev[v] ← u
Q.decrease_priority(v,alt)
end if
end if
end for
end while
return prev[]
我认为,如果v is scanned already or not
的路径需要更新,那么检查v
将来会阻止任何机会。
更新
我已经对页面进行了编辑,current Dijkstra's algorithm wiki page现在正确无误。
答案 0 :(得分:2)
不需要旗帜。只需看看伪代码的这一部分:
if v is not yet scanned:
alt = dist[u] + length(u, v)
if alt < dist[v]
dist[v] ← alt
prev[v] ← u
Q.decrease_priority(v,alt)
end if
end if
如果你检查不同的部分:
alt
似乎是一个仅在此处用作临时变量的局部变量,因此写入它并不会在其他任何地方产生任何影响。v
已从队列中删除,则其路径最多只要u
的路径,否则首先提取u
。v
,则dist[v] <= dist[u] <= alt
。在这种情况下,比较alt < dist[v]
为false,无论如何都会跳过其余的代码。只是解释一下,考虑一下优先级队列的作用。它包含按最短已知路径排序的节点。当从队列中提取节点时,所有节点在最远离该节点之前的所有节点以及之后的所有节点将至少与该节点一样远。由于所有较近的节点都已经处理过,所以发现到这些节点之一的任何新路径都将通过至少相距很远的节点。这意味着,来自仍在队列中的节点的提取节点不能有任何更短的路由,因此仅仅检查alt < dist[v]
就已经排除了那些被扫描的节点。
答案 1 :(得分:-1)
需要检查V是否已经扫描。
在第一个周期,我们找到顶点(V1),它是源顶点(S1)的邻居顶点的最小代价。
在第二个周期,我们不应该从顶点(V1)反转回源顶点(S1)。
当长度(S1,V1)是邻居成本顶点(V1)的最小值时,反向返回源顶点(S1)。
没有检查V扫描的代码是否会导致某些情况下的循环。