我知道這是一個伸手可及的距離,但我正在關注Princeton's course on Algorithm。我試圖使用Bellman Ford算法來檢測邊緣加權有向圖中的負循環。使用貝爾曼福特算法檢測負循環
There is a negative cycle reachable from the source if and only if the queue is
nonempty after the Vth pass through all the edges. Moreover, the subgraph of
edges in our edgeTo[] array must contain a negative cycle.
完整的代碼實現,請訪問:BellmanFordSP.java和EdgeWeightedDirectedCycle.java。具體來說,我堅持在這一點上:
public class BellmanFordSP
{
private double[] distTo; // distTo[v] = distance of shortest s->v path
private DirectedEdge[] edgeTo; // edgeTo[v] = last edge on shortest s->v path
private boolean[] onQueue; // onQueue[v] = is v currently on the queue?
private Queue<Integer> queue; // queue of vertices to relax
private int cost; // number of calls to relax()
private Iterable<DirectedEdge> cycle;// negative cycle (or null if no such cycle)
// Computes a shortest paths tree from s to every other vertex
public BellmanFordSP(EdgeWeightedDigraph G, int s)
{
distTo = new double[G.V()];
edgeTo = new DirectedEdge[G.V()];
onQueue = new boolean[G.V()];
for (int v = 0; v < G.V(); v++)
distTo[v] = Double.POSITIVE_INFINITY;
distTo[s] = 0.0;
// Bellman-Ford algorithm
queue = new Queue<Integer>();
queue.enqueue(s);
onQueue[s] = true;
while (!queue.isEmpty() && !hasNegativeCycle())
{
int v = queue.dequeue();
onQueue[v] = false;
relax(G, v);
}
}
// relax vertex v and put other endpoints on queue if changed
// G.V() gives number of vertices in G
// G.adj(v) returns an Iterable of edges emanating from vertex v.
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 (!onQueue[w])
{
queue.enqueue(w);
onQueue[w] = true;
}
}
if (cost++ % G.V() == 0) // <-- what does this check do ?
findNegativeCycle();
}
}
// Is there a negative cycle reachable from the source vertex s?
public boolean hasNegativeCycle()
{
return cycle != null;
}
// Returns a negative cycle reachable from the source vertex s
public Iterable<DirectedEdge> negativeCycle()
{
return cycle;
}
// by finding a cycle in predecessor graph
private void findNegativeCycle()
{
int V = edgeTo.length;
EdgeWeightedDigraph spt = new EdgeWeightedDigraph(V);
for (int v = 0; v < V; v++)
if (edgeTo[v] != null)
spt.addEdge(edgeTo[v]);
EdgeWeightedDirectedCycle finder = new EdgeWeightedDirectedCycle(spt);
cycle = finder.cycle();
}
這個條件是什麼意思:cost++ % G.V() == 0
。 爲什麼我們只在這個特定的條件下檢查負循環?