我在这里有一个更智能的Bellman-Ford版本:
//Queue Q; source s; vertices u, v
Q ← s // Q holds vertices whose d(v) values have been updated recently.
While (Q !empty)
{
u ← Dequeue(Q)
for each neighbor v of u
{
Relax(u, v)
if d(v) was updated by Relax and v not in Q
Enqueue(v)
}
}
任何人都可以想到这种算法受(V * E)时间复杂度限制的图形类型,其中v = #vertices,E = #edges
我想看看这个陷阱的位置。
答案 0 :(得分:3)
自从我上次考虑短路径算法以来已经好几年了,如果我忘记了什么,请纠正我。
首先,我们首先排除负加权周期的情况,但它可能是最坏情况表现的来源。
我们假设你访问了一个完整的图表。从第一个节点开始,您将对V-1节点进行排队,因为所有节点都是s的邻居。假设你运气不好,你排队的最后一个节点是所有节点的最短路径的一部分。因此,您必须排队V-2节点(所有节点,减去源节点和您正在评估的节点......)。现在让我们非常不走运,并假设您排队的最后一个节点再次成为所有剩余节点的路径的一部分......您将必须排队V-3节点等。
因此,如果一切都出错,您将评估V-1 * V-2 * ... * 3 * 2 * 1节点。您应该很容易找到这个总和如何| E |。
对于每个节点,你在做什么?检查每个邻居。每个节点都有V-1个邻居。
我们已经在你的算法的O(| V-1 | | E |)最坏情况复杂度。 如果我记得很清楚,Bellman-Ford算法会检查每个边缘以确保没有负加权循环,所以你应该这样做;这增加了1到V-1,又名(| V | | E |)最坏情况的复杂性。
答案 1 :(得分:0)
我不确定这是否有效,但假设确实如此,你可以创建一个BF没有改进的情况。创建开始和结束节点,并在之间放置连接两者的N个顶点。算法仍然需要考虑每条路径。
答案 2 :(得分:0)
这是对Ford-Bellman的改进。它比平时更快地实现。当然,在最坏的情况下,时间复杂度可以是O(n.m)。但是,很难创建一个输入来破解这个算法。在比赛中,排队的福特 - 贝尔曼比Dijkstra执行得更快。但是,您必须创建一个数组调用Inqueue来检查当前元素是否在队列中:
qu : queue;
inqueue : array of bool;
for i in [1..n] do { d[i]=oo; inqueue[i]=false; }
qu.push(start);
d[start] = 0;
repeat
u=qu.pop;
inqueue[u]=false;
for v in adj[u] do
if minimize(d[v], d[u]+uv) then
if !inqueue[v] then
{ inqueue[v] = true; qu.push(v); }
until qu.empty;
print d[target];