I was studying queue-based
approach for Bellman-Ford algorithm
for single source shortest path from Robert Sedgewick and Kevin Wayne - Algorit
Accordingly, to implement negativeCycle() BellmanFordSP.java builds an edge-weighted digraph from the edges in edgeTo[] and looks for a cycle in that digraph. To find the cycle, it uses EdgeWeightedDirectedCycle.java, a version of DirectedCycle.java from Section 4.3, adapted to work for edge-weighted digraphs. We amortize the cost of this check by performing this check only after every Vth call to relax().
In other words, you can check more often, but then you risk performance loss.
while
loop in the constructor. However, in the worst case the relax
method can detect the cycle by checking first edge in the for
loop, and instead of exiting it will continue and check other edges (max V-2
of them). With your suggested improvement that can save significant amount of time.Very happy to see the answers by Miljen Mikic. It really helps to understand the algorithm. However, I still have another question. In the text, it says "To complete the implementation, we need to ensure that the algorithm terminates after V passes. One way to achieve this end is to explicitly keep track of the passes." Here, I believe the variable "cost" is the count of the passes, but shouldn't the lines
if (cost++ % G.V() == 0)
findNegativeCycle();
be at least outside of the for loop? Like
private void relax(EdgeWeightedDigraph G, int v)
{
for (DirectedEdge e : G.adj(v)
{
int w = e.to();
if (distTo[w] > distTo[v] + e.weight())
{
distTo[w] = distTo[v] + e.weight();
edgeTo[w] = e;
if (!onQ[w])
{
q.enqueue(w);
onQ[w] = true;
}
}
}
if (cost++ % G.V() == 0)
findNegativeCycle();
}
Actually even it's outside of the for loop, it's not the best solution, as during each pass, there could be multiple vertices to be relaxed. So it could be designed better in the constructor of BellmanFordSP by remembering how many vertices to be relaxed during each pass. Am I correct? Thanks!