Dijkstra的算法和贪婪策略

时间:2018-12-03 22:37:20

标签: c++ algorithm dijkstra

在理解贪心策略如何工作以及Dijkstra的算法如何跟踪最短路径时,我似乎有些麻烦。供参考,这是Dijkstra算法的伪代码

DijkstrasAlgorithm(G, w, s)
    InitalizeSingleSource(G, s)
    S = 0
    Q = G.V
    while Q != 0
        u = ExtractMin(Q)
        S = S∪{u}
        for each vertex v ∈ G.Adj[u]
            Relax(u, v, w)

请考虑以下重量方向图。

有5个顶点:s,t,x,y,z 有10条边线:

s->t = 3
s->y = 5
t->y = 2
t->x = 6
y->t = 1
y->x = 4
y->z = 6
x->z = 2
z->x = 7
z->s = 3

我们的目标是找到从s到x的最短路径。我的答案是长度为9的s-> t-> y-> x,我假设伪代码中的“ S”是最短路径,并且将minQ中的每个ExtractMin添加到了路径上。

但是,我的老师告诉我这是错误的。正确答案是长度为9的s-> t-> x。我们答案的区别在于是否包含y。我的老师说,由于s-> t-> x是“先找到”的,因此不会更新为等长的s-> t-> y-> x。

这使我感到困惑。 Dijkstra的算法使用贪婪策略,我认为贪婪策略总是选择当时可用的最短路径。并且,当在t-> y和t-> x之间选择时,t-> y较短,因此应该选择。

我的问题是:

1)在什么情况下,贪婪策略不会选择最终结果的最短路径?

2)如果在minQ上使用ExtractMin不是我们如何跟踪从s到x的整体路径,那么我们如何跟踪完整的路径?

1 个答案:

答案 0 :(得分:2)

您老师的答案假设我们按“最短优先,先中断先发现”的顺序探索路径。

首先,我们探索# flatten the list S = S.apply(lambda x: [i for s in x for i in s]) # pick alternate values and create a data frame S = S.apply(lambda x: [x[::2], x[1::2]]).reset_index()[0].apply(pd.Series) # name index S.index = ['a','b'] 0 1 a [0, 2, 3] [1, 3, 4] b [5, 7, 9] [6, 8, 10] ,将s->t中成本为x的{​​{1}}放到要探索“某天”的事物列表中。但是我们首先探索s->t->x,因为它更短。到那时,我们看到s->t->y是一个选项,也是成本9。但是,由于这不是改进,因此我们将其删除。

因此,一旦到达长度为9的路径,我们就会发现s->t->y->x是因为它首先进入队列。

如果您修改s->t->x来保存一条可能的路径,且其效果好于或等于目前找到的最佳路径,您将得到答案。这样会得到正确的答案。

关于从末端提取路径的方式,每个节点都知道如何到达该路径。因此,从末尾开始,然后按照Cookie跟踪向后查找反向路径,然后将其反向以获取实际路径。