我正在研究queue-based
针对来自Bellman-Ford algorithm
的单一来源最短路径的Robert Sedgewick and Kevin Wayne - Algorithms, 4th edition
方法
来自book的算法的源代码出现在此链接http://algs4.cs.princeton.edu/44sp/BellmanFordSP.java。
我有两点是怀疑,另一点是代码改进建议。
在上面的方法中,下面是用于放松距离顶点的松弛方法的代码。
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是顶点数。
但我认为在基于队列的方法中,他们使用除数来定期检查周期是否已经发生。可以发生循环
在上述条件之前或之后是真的。如果在上述条件为真后发生循环,则算法必须等到下一个条件为止
如果(cost++ % G.V() == 0)
为真,则检测周期为true,没有必要完全发生周期。所以我认为除数可以是足够小的任何数,以便我们可以在适当的时间间隔后检查周期。
我是否正确地想到了这一点?
代码改进建议是findNegativeCycle()
方法可用于在循环发生时返回true。从而。这种情况 -
if (cost++ % G.V() == 0) { findNegativeCycle(); }
可以更改为 -
if (cost++ % G.V() == 0)
if(findNegativeCycle()){
return;
}
即使findNegativeCycle()
方法找到了一个循环,代码for循环也会继续运行。所以我们可以在循环发生时返回,而不是处理for循环的其余部分。
请分享您对以上2点的想法。 提前谢谢。
答案 0 :(得分:3)
因此,要实现negativeCycle()BellmanFordSP.java构建一个 edgeTo []中边缘的边加权有向图,并寻找一个循环 在那个有向图。为了找到循环,它使用 EdgeWeightedDirectedCycle.java,一个版本的DirectedCycle.java来自 第4.3节,适用于边缘加权有向图。 我们摊销 只有在每个Vth之后执行此检查才能获得此检查的成本 打电话给放松()。
换句话说,你可以更频繁地检查,但是你会冒失去性能的风险。
while
循环中检查负循环的存在。但是,在最坏的情况下,relax
方法可以通过检查for
循环中的第一个边缘来检测周期,而不是退出它将继续并检查其他边缘(最大V-2
)。使用您建议的改进可以节省大量时间。答案 1 :(得分:0)
非常高兴看到Miljen Mikic的答案。理解算法确实很有帮助。但是,我还有另一个问题。在文中,它说“要完成实现,我们需要确保算法终止 V过后。实现这一目标的一种方法是明确地跟踪传球。“在这里,我相信变量”成本“是传球的数量,但不应该是线
if (cost++ % G.V() == 0)
findNegativeCycle();
至少在for循环之外?像
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();
}
实际上,即使它在for循环之外,它也不是最好的解决方案,因为在每次传递过程中,可能会有多个顶点要放松。因此,通过记住每次传递中要放松的顶点数,可以在BellmanFordSP的构造函数中更好地设计它。我对么?谢谢!