只有两种可能成本的完整图表。从 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 的最短路径的成本是多少的主要内容,如果未能解决你的问题,请参考以下文章