我正在研究 此链接http://algs4.cs.princeton.edu/44sp/BellmanFordSP.java上针对单个源最短路径的queue- based方法,Bellman-Ford algorithm该方法Robert Sedgewick and Kevin Wayne - Algorithms, 4th edition来自本书的算法。
queue- based
Bellman-Ford algorithm
Robert Sedgewick and Kevin Wayne - Algorithms, 4th edition
我有两点,一个是疑问,另一个是代码改进建议。
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){ findNegativeCycle(); }
}
在此方法中,在找到负循环之前使用以下条件。
if (cost++ % G.V() == 0){ findNegativeCycle(); }
上面他们用成本除以vertices图中的数目来检查negative cycle。可能是因为松弛完成V-1了Vth一段时间,并且如果松弛运行了一段时间,则意味着它具有循环,其中V是顶点数。
vertices
negative cycle
V-1
Vth
但是我认为在基于队列的方法中,他们使用除数来定期检查周期是否发生。在上述条件成立之前或之后可能会发生一个周期。如果在上述条件为真之后发生循环,则算法必须等到下一个条件为真时才能检测到循环,如果(cost++ % G.V() == 0)为真,则不必精确地发生循环。因此,我认为除数可以是足够小的任何数字,以便我们可以在适当的时间间隔后检查周期。我是这样认为的吗?
(cost++ % G.V() == 0)
findNegativeCycle()
if (cost++ % G.V() == 0) { findNegativeCycle(); }
可以更改为-
if (cost++ % G.V() == 0) if(findNegativeCycle()){ return; }
即使findNegativeCycle()方法找到一个循环,for循环中的代码也会继续运行。因此我们可以返回是否发生循环,而不是处理其余的for循环。
请分享您对以上2点的看法。提前致谢。
因此,为了实现negativeCycle(),BellmanFordSP.java从edgeTo []的边缘构建了一个边缘加权的有向图,并在该有向图中寻找一个循环。为了找到循环,它使用EdgeWeightedDirectedCycle.java(第4.3节中DirectedCycle.java的一个版本),适用于边缘加权有向图。 我们仅在每次Vth调用Relax()之后才执行此检查,从而摊销此检查的费用 。
换句话说,您可以更频繁地检查,但是这样会冒着性能损失的风险。
while
relax
for
V-2