问题
I've seen quite a few posts (viz. post1, post2, post3) on this topic but none of the posts provides an algorithm to back up respective queries. Consequently I'm not sure to accept the answers to those posts.
Here I present a BFS based shortest-path (single source) algorithm that works for non-negative weighted graph. Can anyone help me understand why BFS (in light of below BFS based algorithm) are not used for such problems (involving weighted graph)!
The Algorithm:
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
Runtime: As far as I see it is O(|V| + |E|) including the initialization cost
If this algorithm resembles any existing one, pls let me know
回答1:
Since the pseudocode is Dijksta's algorithm with FIFO queue instead of priority queue that is always sorted based on the distances. The crucial invariant that each visited (black) vertex has computed shortest distance possible so far will not be necessarily true. And that is the reason why priority queue is a must for computation of distance in (positively) weighted graphs.
You can use your algorithm for unweighted graphs or make it unweighed by replacing each edge with weight n
with n-1
vertexes connected by edges with weight 1.
Counterexample:
State of the computation after first Q.enqueue(s)
:
State of the computation after first iteration:
Important for this graph to be a counterexample is that adj[u] = adj[S] = [F, M]
and not [M, F]
, hence F
is queued first by Q.enqueue(v)
State of the computation after second iteration:
Since vertex F
is dequeued first by u = Q.dequeue()
(unlike when distance priority queue is used), this iteration will not update any distance, F
will become black and the invariant will be violated.
State of the computation after the final iteration:
回答2:
I used to have same confusion. Check out SPFA algorithm. When the author published this algorithm back in 1994, he claimed it has a better performance than Dijkstra with O(E) complexity, which is wrong.
You can treat this algorithm as an variation/improve of Bellman-Ford. Worst case complexity is still O(VE), since one node may be add/remove from the queue multiple times. But for random sparse graph, it definitely outperforms original Bellman-Ford since it skip lots of unnecessary relaxing steps.
Although this name "SPFA" seems not well accepted in academia, upon published it became very popular among ACM students due to its simplicity and ease to implement. Performance wise Dijkstra is preferred.
回答3:
It looks like you implemented Dijkstra's classical algorithm, without a heap. You are going through the matrix through each edge and then seeing if you can improve the distance.
回答4:
Normally people say it's BFS when there is no edge weight.
BFS: graph with constant edge weight.
Dijkstra: graph with edge weights (can handle some negative edges if
it doens't have negative cycle)Bellman-ford and SPFA: graph with negative cycle.
Your code is Dijkastra or SPFA variant and not a simple BFS (although it IS based on BFS based alrorithm)
来源:https://stackoverflow.com/questions/38382690/a-bfs-algorithm-for-weighted-graphs-to-find-shortest-distance