Algorithm 只有两种可能成本的完整图表。什么';s最短路径';s成本从0到N-1

Algorithm 只有两种可能成本的完整图表。什么';s最短路径';s成本从0到N-1,algorithm,graph,dijkstra,shortest-path,breadth-first-search,Algorithm,Graph,Dijkstra,Shortest Path,Breadth First Search,给出了一个具有N个顶点的完全无向图。除了K条边外,其他所有边的代价都是a。这些K条边的代价是B,您知道它们(作为对的列表)。从节点0到节点N-1的最小成本是多少 2 <= N <= 500k 0 <= K <= 500k 1 <= A, B <= 500k 问题是,这会占用大量时间,因为对于每个节点,必须从0到N-1进行循环,才能找到“好”的相邻节点 有谁有更好的主意吗?多谢各位 编辑:这里有一个来自ACM竞赛的链接:正如您正确指出的,当a>B和从0到n-

给出了一个具有N个顶点的完全无向图。除了K条边外,其他所有边的代价都是a。这些K条边的代价是B,您知道它们(作为对的列表)。从节点0到节点N-1的最小成本是多少

2 <= N <= 500k
0 <= K <= 500k
1 <= A, B <= 500k 
问题是,这会占用大量时间,因为对于每个节点,必须从0到N-1进行循环,才能找到“好”的相邻节点

有谁有更好的主意吗?多谢各位


编辑:这里有一个来自ACM竞赛的链接:

正如您正确指出的,当a>B和从0到n-1的edge的成本为a时,问题就出现了

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

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


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

如果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++
G(k)是k条廉价边可到达的节点集,且不少于k条。我们从G(0)={v0}开始
而G(k)不是空的,G(k)不包含vN-1和k*A

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

我提出了一个更一般的问题的解决方案,其中可能有两种以上的边,并且边权重没有边界。对于您的场景,这个想法可能有点过头了,但是实现非常简单,因此这可能是解决问题的一个好方法

您可以使用段树来提高Dijkstra的效率。你需要手术


  • 在给定U、L、R的范围内设置上限;对于所有的x[i]和L来说,这是一个艰苦的案例工作:

  • Atriple连接
  • Btriple连接
  • 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)的时间内找到每个顶点的距离


  • 当a>B且从0到N-1的边花费a时,也会出现问题。在这种情况下,您可能能够形成k*BG(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++