具有固定边数的最短路径

发布于 2024-08-10 02:41:54 字数 202 浏览 3 评论 0原文

在有效的时间内找到通过图形的最短路径,附加约束是该路径必须恰好包含 n 个节点。

我们有一个有向加权图。它可能包含也可能不包含循环。我们可以使用 Dijkstra 算法轻松找到最短路径,但 Dijkstra 算法不保证边的数量。

我们能想到的最好办法是保留通往节点的最佳 n 条路径的列表,但这比普通 Dijkstra 的方法占用大量内存。

Find the shortest path through a graph in efficient time, with the additional constraint that the path must contain exactly n nodes.

We have a directed, weighted graph. It may, or may not contain a loop. We can easily find the shortest path using Dijkstra's algorithm, but Dijkstra's makes no guarantee about the number of edges.

The best we could come up with was to keep a list of the best n paths to a node, but this uses a huge amount of memory over vanilla Dijkstra's.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

极致的悲 2024-08-17 02:41:54

这是一种简单的动态规划算法。

假设我们想要从顶点 x 到顶点 y

制作一个表 D[.,.],其中 D[v,k] 是从从顶点x开始到顶点v

Initially D[x,1] = 0. Set D[v,1] = infinity for all v != x.
For k=2 to n:
  D[v,k] = min_u D[u,k-1] + wt(u,v), where we assume that wt(u,v) is infinite for missing edges. 
  P[v,k] = the u that gave us the above minimum.

最短路径的长度将存储在 D[y,n] 中。

如果我们有一个边较少的图(稀疏图),我们可以通过仅搜索 v 连接到的 u 来有效地做到这一点。这可以通过邻接列表数组来最佳地完成。

恢复最短路径:

Path = empty list
v = y
For k= n downto 1:
  Path.append(v)
  v = P[v,k]
Path.append(x)
Path.reverse()

最后一个节点是y。之前的节点是P[y,n]。我们可以继续向后跟踪,最终将得到 vP[v,2] = x

It is a simple dynamic programming algorithm.

Let us assume that we want to go from vertex x to vertex y.

Make a table D[.,.], where D[v,k] is the cost of the shortest path of length k from the starting vertex x to the vertex v.

Initially D[x,1] = 0. Set D[v,1] = infinity for all v != x.
For k=2 to n:
  D[v,k] = min_u D[u,k-1] + wt(u,v), where we assume that wt(u,v) is infinite for missing edges. 
  P[v,k] = the u that gave us the above minimum.

The length of the shortest path will then be stored in D[y,n].

If we have a graph with fewer edges (sparse graph), we can do this efficiently by only searching over the u that v is connected to. This can be done optimally with an array of adjacency lists.

To recover the shortest path:

Path = empty list
v = y
For k= n downto 1:
  Path.append(v)
  v = P[v,k]
Path.append(x)
Path.reverse()

The last node is y. The node before that is P[y,n]. We can keep following backwards, and we will eventually arrive at P[v,2] = x for some v.

始终不够 2024-08-17 02:41:54

我想到的替代方案是深度优先搜索(与 Dijkstra 的广度优先搜索相反),修改如下:

  • 如果超过所需的顶点数,则停止“深度”

  • 记录具有正确节点数的最短找到的(迄今为止)路径。

运行时间可能很糟糕,但它应该在使用非常合理的内存量的情况下得出正确的结果。

The alternative that comes to my mind is a depth first search (as opposed to Dijkstra's breadth first search), modified as follows:

  • stop "depth"-ing if the required vertex count is exceeded

  • record the shortest found (thus far) path having the correct number of nodes.

Run time may be abysmal, but it should come up with the correct result while using a very reasonable amount of memory.

却一份温柔 2024-08-17 02:41:54

有趣的问题。您是否讨论过使用启发式图搜索(例如 A*),为超过或低于节点数添加惩罚?这可能会也可能不会被接受,但如果它确实有效,它可能比保留所有潜在路径的列表更有效。

事实上,您也许可以使用回溯来限制您讨论的 Dijkstra 变体所使用的内存量。

Interesting problem. Did you discuss using a heuristic graph search (such as A*), adding a penalty for going over or under the node count? This may or may not be admissible, but if it did work, it may be more efficient than keeping a list of all the potential paths.

In fact, you may be able to use backtracking to limit the amount of memory being used for the Dijkstra variation you discussed.

谜泪 2024-08-17 02:41:54

算法的大致思路:

设 A 为起始节点,设 S 为一组节点(加上一条路径)。不变的是,在步骤 n 结束时,S 将是距离 A 正好 n 步的所有节点,并且路径将是该长度的最短路径。当 n 为 0 时,该集合为 {A(空路径)}。给定步骤 n - 1 处的这样一个集合,您可以从一个空集合 S1 开始到达步骤 n,并且

for each (node X, path P) in S
  for each edge E from X to Y in S, 
    If Y is not in S1, add (Y, P + Y) to S1
    If (Y, P1) is in S1, set the path to the shorter of P1 and P + Y

只有 n 个步骤,并且每个步骤应小于 max(N, E),这使得
对于稠密图,整个算法为 O(n^3);对于稀疏图,整个算法为 O(n^2)。

该算法取自 Dijkstra 算法,尽管它是一种不同的算法。

A rough idea of an algorithm:

Let A be the start node, and let S be a set of nodes (plus a path). The invariant is that at the end of step n, S will all nodes that are exactly n steps from A and the paths will be the shortest paths of that length. When n is 0, that set is {A (empty path)}. Given such a set at step n - 1, you get to step n by starting with an empty set S1 and

for each (node X, path P) in S
  for each edge E from X to Y in S, 
    If Y is not in S1, add (Y, P + Y) to S1
    If (Y, P1) is in S1, set the path to the shorter of P1 and P + Y

There are only n steps, and each step should take less than max(N, E), which makes the
entire algorithm O(n^3) for a dense graph and O(n^2) for a sparse graph.

This algorith was taken from looking at Dijkstra's, although it is a different algorithm.

千年*琉璃梦 2024-08-17 02:41:54

假设我们想要 k 步骤中从节点 x 到 y 的最短距离
简单的 dp 解决方案是

A[k][x][y] = min over { A[1][i][k] + A[t-1][k][y] }
k 从 0 到 n-1 变化

A[1][i][j] = r[i][j]; p[1][i][j]=j;
for(t=2; t<=n; t++)
for(i=0; i<n; i++) for(j=0; j<n; j++)
{
A[t][i][j]=BG; p[t][i][j]=-1;
for(k=0; k<n; k++) if(A[1][i][k]<BG && A[t-1][k][j]<BG)
if(A[1][i][k]+A[t-1][k][j] < A[t][i][j])
{
A[t][i][j] = A[1][i][k]+A[t-1][k][j];
p[t][i][j] = k;
}
}

trace back the path
void output(int a, int b, int t)
{
while(t)
{

cout<<a<<" ";
a = p[t][a][b];
t--;
}
cout<<b<<endl;
}

let say we want shortest distance from node x to y of k step
simple dp solution would be

A[k][x][y] = min over { A[1][i][k] + A[t-1][k][y] }
k varies from 0 to n-1

A[1][i][j] = r[i][j]; p[1][i][j]=j;
for(t=2; t<=n; t++)
for(i=0; i<n; i++) for(j=0; j<n; j++)
{
A[t][i][j]=BG; p[t][i][j]=-1;
for(k=0; k<n; k++) if(A[1][i][k]<BG && A[t-1][k][j]<BG)
if(A[1][i][k]+A[t-1][k][j] < A[t][i][j])
{
A[t][i][j] = A[1][i][k]+A[t-1][k][j];
p[t][i][j] = k;
}
}

trace back the path
void output(int a, int b, int t)
{
while(t)
{

cout<<a<<" ";
a = p[t][a][b];
t--;
}
cout<<b<<endl;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文