只有两种可能成本的完整图表。从 0 到 N - 1 的最短路径的成本是多少

Posted

技术标签:

【中文标题】只有两种可能成本的完整图表。从 0 到 N - 1 的最短路径的成本是多少【英文标题】:Complete graph with only two possible costs. What's the shortest path's cost from 0 to N - 1 【发布时间】:2014-04-12 12:08:10 【问题描述】:

给定一个包含 N 个顶点的完全无向图。除 K 条边之外的所有边的成本均为 A。这些 K 条边的成本为 B,您知道它们(作为对列表)。从节点 0 到节点 N - 1 的最小成本是多少。

2 <= N <= 500k
0 <= K <= 500k
1 <= A, B <= 500k 

问题显然是,当这 K 条边的成本高于其他边时,节点 0 和节点 N - 1 由 K 边连接。

Dijkstra 不起作用。我什至尝试过与 BFS 非常相似的东西。

Step1: Let G(0) be the set of "good" adjacent nodes with node 0.
Step2: For each node in G(0):
              compute G(node)
              if G(node) contains N - 1
                  return step

              else
                  add node to some queue
       repeat step2 and increment step

问题在于,这会占用大量时间,因为您必须对每个节点进行从 0 到 N - 1 的循环才能找到“好的”相邻节点。

有没有人有更好的想法?谢谢。

编辑:这是 ACM 比赛的链接:http://acm.ro/prob/probleme/B.pdf

【问题讨论】:

A > B 并且从 0 到 N-1 的边花费 A 时也是一个问题。在这种情况下,您也许可以形成 k*B 是的,但这并不是真正的问题,因为您只有 500K B 边。你可以“负担”在那些 B 边图上做 BFS。问题是当你必须探索互补图时(因为那些是便宜的边)。 什么意思,Dijkstra 不工作?是不是太贵了,还是有什么问题导致它失败? 我的意思是 Dijktra 对于这个问题来说太耗时了。 O(E * logV) 意味着在最坏的情况下大约 10^15 次操作。太多了。 @FlaviusAnton 这个问题在线上的某个地方吗?我想解决它 【参考方案1】:

这是一项费力的案例工作:

    A trivial 连接。 B 琐碎。 B 在只有 K 条边的图上执行 BFS。

    A 您可以检查 O(N) 时间是否存在长度为 2*A 的路径(尝试中间的每个顶点)。

    要检查以下算法的其他路径长度应该可以解决问题: 让 X(d) 是通过使用从 0 开始的 d 条较短边可到达的节点集。您可以使用以下算法找到 X(d):获取距离未知的每个顶点 v,并从 X(d-1) 迭代检查 v 和顶点之间的边)。如果你找到了短边,那么 v 在 X(d) 中,否则你踩到了长边。由于最多有 K 个长边,因此您最多可以踩到它们 K 次。因此,您最多应该在 O(N + K) 时间内找到每个顶点的距离。

【讨论】:

这并不完全正确。我有一个带有 120k 节点的图示例,“好”边的成本为 1,“坏”边的成本为 100000,最短路径的长度为 5,大于 3。【参考方案2】:

我提出了一个解决方案来解决一个更普遍的问题,即您可能有两种以上类型的边并且边权重没有限制。对于您的场景,这个想法可能有点矫枉过正,但实现非常简单,因此它可能是解决问题的好方法。

您可以使用分段树来提高 Dijkstra 的效率。您将需要操作

在给定 U、L、R 的范围内设置上限;对于 L 求全局最小值

上界可以延迟下推,所以两者都可以在 O(log n) 内实现

当放宽输出边时,查找成本为 B 的边,对它们进行排序并立即更新它们之间的范围。

如果您预先对所有边进行排序(按输出顶点),则运行时间应该是 O(n log n + m log m)。

编辑:被这种方法接受。它的好处是它避免了任何类型的特殊外壳。它仍然是大约 80 行代码。

【讨论】:

【参考方案3】:

在 A

G(k) is the set of nodes reachable by k cheap edges and no less. We start with G(0) = v0

while G(k) isn't empty and G(k) doesn't contain vN-1 and k*A < B
  A = array[N] of zeroes
  for every node n in G(k)
    for every expensive edge (n,m)
      A[m]++
  # now we have that A[m] == |G(k)| iff m can't be reached by a cheap edge from any of G(k)
  set G(k+1) to m; A[m] < |G(k)| except n; n is in G(0),...G(k)
  k++

这样可以避免遍历(许多)廉价边,而只遍历相对较少的昂贵边。

【讨论】:

【参考方案4】:

正如您正确指出的那样,当 A > B 并且从 0 到 n-1 的边的成本为 A 时,问题就出现了。

在这种情况下,您可以简单地删除图中成本为 A 的所有边。这是因为最优路线应该只有成本为 B 的边。

然后您可以执行简单的 BFS,因为所有边的成本都相同。正如此链接所指出的,它将为您提供最佳性能:Finding shortest path for equal weighted graph

此外,当总成本超过 A 时,您可以停止 BFS。

【讨论】:

当然,你是对的,但这是微不足道的。我完全谈论相反的情况,当那些 K 边缘(更少)更昂贵时。因为那时你必须对具有更多边的互补图进行 BFS。 同样的算法也可以应用于相反的情况。我指出的链接表明 BFS 是解决此问题的最佳方法。如果在 BFS 之前删除不必要的边,则不需要每次从 0 循环到 N-1。

以上是关于只有两种可能成本的完整图表。从 0 到 N - 1 的最短路径的成本是多少的主要内容,如果未能解决你的问题,请参考以下文章

SWF版本到Flash版本的图表

两种背包尺寸的多维成本0-1背包问题

kcachegrind:如何绘制完整的调用图?

从完整图计算最短路径[关闭]

曹总的新项目介绍

修改 Dijkstra 算法以处理具有多个可能成本的边