想象一下这个问题。这些边就像道路,而边的权重是车辆在道路上行驶的最大重量限制。我们想要开一辆从A到B的最大卡车。因此,沿给定路径行驶的卡车的最大允许重量是该路径中所有边的最小重量。我想要从A到B的所有路径中具有最大的最大允许重量。
我可以使用某种Dijkstra算法来解决这个问题吗?我不确定如何用算法的形式表达这个问题并实现它。非常感谢任何帮助。
更新:我尝试了一些对我无效的方法。每个节点必须有每个入边的一个最大卡车。
迪杰斯特拉算法应该可以使用,但在这种情况下,您的“距离”有些奇怪。您的“距离”是您可以到达节点的最大卡车大小。我们称其为节点v的M[v]。您需要按照从最大M[v]到最小M[v](与正常的Dijkstra相反)的顺序处理节点,并计算从v到w的每个边缘e:
M[w] = max(M[w], min(e.weight, M[v]))
这几乎与最大流问题完全相同,可以使用Ford-Fulkerson算法有效地解决。
正如Keith在评论中指出的那样,必须稍微改变算法以仅查找最大化最小路径段的一条路径,因为卡车不能分成多个部分。
如果我理解正确的话,你是在问:“从A到B最大的卡车是多大?”
要应用Dijkstra算法,您需要一种对“成本”进行建模的方法。如果想使用标准实现,则可以将权重的倒数分配给成本。因此,最高成本的边缘是具有最小最大权重的边缘。当然,由于您可能想使用漂亮的整数,因此您可以简单地修改比较而不是实际使用倒数。
这既不是最短路径问题,也不是最大流问题。实际上并不存在问题。他说 - 想要从 A 到 B 的所有路径的最大权重。因此通过 BFS 生成所有从 A 开始的路径。对于所有以 B 结尾的路径,找到路径边缘的最小权重。
edge_cost
等于1/(允许的最大卡车重量),
给定路线的total_cost
是该路线中所有边的个体edge_cost
的最大值。上面的各种答案都提出了使用修改后的权重函数的Dijkstra算法。例如,w(e) = -c(e)
或'w(e) = 1/c(e)',其中w(e)
是算法使用的边的权重,c(e)
是原始问题公式中边的容量。
这些方法不起作用。
很容易就能找到反例证明这会产生错误的结果。例如,考虑以下图形:
a---3-->b---3--->c---3-->d
\ ^
\ |
\----------3----------|
a
(算法公式中节点a
的距离)的值为零。从a
到d
的两条路径在此问题中是等效的。然而,如果我们只是取反边缘容量,使用长路径的距离(d)将是(-3)+(-3)+(-3)=-9
,而使用短路径则是-3
。如果我们反转边缘容量,则使用长路径的距离(d)将是(1/3)+(1/3)+(1/3)=1
,而使用短路径则仅为(1/3)
。
修改算法的松弛步骤是可行的,即使用函数min
和大于号(>
)代替加法(+
)和小于号(<
),并使用最大堆而不是最小堆。如果我们取反边权重并使用小于号,则可以避免最后两个修改,但我们无法避免替换+
,因为我们需要某个运算符@
,其中对于所有a
值,a @ a = a
,而+
仅适用于a=0
。
因此,我看到的唯一正确答案是Keith Randall给出的第一个答案。
一个好的练习是正式证明修改后的算法是正确的。需要证明的是:
- 如果u
是任何循环迭代中具有最大值d(u)
的节点,则涉及未标记节点的路径不能创建到u
的路径,使得距离大于d(u)
。
u
作为具有最大距离的节点),而生成路径的距离是通过连续调用min
产生的,因此它只能变小,而不能变大。