我在这个主题上看过很多帖子(即post1,post2,post3)但是这些帖子都没有提供备份相应查询的算法。因此,我不确定接受这些帖子的答案。
在这里,我提出了一个基于BFS的最短路径(单源)算法,适用于非负加权图。任何人都可以帮助我理解为什么BFS(根据以下基于BFS的算法)不用于此类问题(涉及加权图)!
算法:
SingleSourceShortestPath (G, w, s):
//G is graph, w is weight function, s is source vertex
//assume each vertex has 'col' (color), 'd' (distance), and 'p' (predecessor)
properties
Initialize all vertext's color to WHITE, distance to INFINITY (or a large number
larger than any edge's weight, and predecessor to NIL
Q:= initialize an empty queue
s.d=0
s.col=GREY //invariant, only GREY vertex goes inside the Q
Q.enqueue(s) //enqueue 's' to Q
while Q is not empty
u = Q.dequeue() //dequeue in FIFO manner
for each vertex v in adj[u] //adj[u] provides adjacency list of u
if v is WHITE or GREY //candidate for distance update
if u.d + w(u,v) < v.d //w(u,v) gives weight of the
//edge from u to v
v.d=u.d + w(u,v)
v.p=u
if v is WHITE
v.col=GREY //invariant, only GREY in Q
Q.enqueue(v)
end-if
end-if
end-if
end-for
u.col=BLACK //invariant, don't update any field of BLACK vertex.
// i.e. 'd' field is sealed
end-while
运行时:据我所知,它是O(| V | + | E |),包括初始化成本
如果此算法类似于任何现有算法,请告诉我
答案 0 :(得分:3)
由于伪代码是Dijksta的算法,其FIFO队列而不是优先级队列,总是根据距离进行排序。到目前为止,每个访问过的(黑色)顶点计算出的最短距离的关键不变量不一定正确。这就是为什么优先级队列是(正)加权图中距离计算必须的原因。
您可以将算法用于未加权的图表,或者通过将权重n
替换为权重为1的边缘连接的n-1
顶点来使每个边缘不加权。
反例:
首先Q.enqueue(s)
之后的计算状态:
第一次迭代后的计算状态:
此图表是一个反例,重要的是adj[u] = adj[S] = [F, M]
而不是[M, F]
,因此F
首先排在Q.enqueue(v)
第二次迭代后的计算状态:
由于顶点F
首先由u = Q.dequeue()
出列(与使用距离优先级队列时不同),此迭代不会更新任何距离,F
将变为黑色且不变量将为侵犯。
最后一次迭代后的计算状态:
答案 1 :(得分:0)
看起来你实现了Dijkstra的经典算法,没有堆。您将遍历每个边缘的矩阵,然后查看是否可以改善距离。
答案 2 :(得分:0)
我以前也有同样的困惑。查看SPFA算法。当作者于1994年发布此算法时,他声称它的算法比Dijkstra的O(E)复杂度更好,这是错误的。
您可以将此算法视为Bellman-Ford的变体/改进。最糟糕的情况仍然是O(VE),因为一个节点可能会多次从队列中添加/删除。但是对于随机稀疏图,由于它跳过了许多不必要的放松步骤,因此它的性能肯定优于原始的Bellman-Ford。
尽管“ SPFA”这个名称在学术界似乎并不为人所接受,但由于其简单易用,在ACM学生中广受欢迎。性能上最好是Dijkstra。
答案 3 :(得分:0)
通常人们说没有边缘重量时是BFS。
BFS :具有恒定边缘权重的图形。
Dijkstra :带有边缘权重的图形(如果
可以处理一些负边缘
它没有负周期)
贝尔曼福德和SPFA :负周期图。
您的代码是Dijkastra或SPFA的变体,而不是简单的BFS(尽管它是 IS 基于基于BFS的算法)