如何找到覆盖有向循环图中所有节点的最短路径?

时间:2022-12-06 23:21:14

I need an example of the shortest path of a directed cyclic graph from one node (it should reach to all nodes of the graph from a node that will be the input).

我需要一个来自一个节点的有向循环图的最短路径的示例(它应该从将作为输入的节点到达图的所有节点)。

Please if there is an example, I need it in C++, or the algorithm.

如果有一个例子,我需要用C ++或算法。

4 个解决方案

#1


EDIT: Oops, misread the question. Thanks @jfclavette for picking this up. Old answer is at the end.

编辑:哎呀,误读了这个问题。谢谢@jfclavette选择了这个。老答案就在最后。

The problem you're trying to solve is called the Travelling salesman problem. There are many potential solutions, but it's NP-complete so you won't be able to solve for large graphs.

您尝试解决的问题称为旅行商问题。有许多潜在的解决方案,但它是NP完全的,所以你将无法解决大型图形。

Old answer:

What you're trying to find is called the girth of a graph. It can be solved by setting the distances from a node to itself to infinity and using the Floyd-Warshall algorithm. The length of the shortest cycle from node i is then just the entry in position ii.

你想要找到的东西叫做图的周长。它可以通过设置从节点到自身的距离到无穷大并使用Floyd-Warshall算法来解决。从节点i开始的最短周期的长度就是位置ii的条目。

#2


In Pseudocode:

//INPUT: graph G = (V,E)
//OUTPUT: shortest cycle length
min_cycle(G)
  min = ∞
  for u in V
    len = dij_cyc(G,u)
    if min > len
      min = len
  return min    

//INPUT: graph G and vertex s
//OUTPUT: minimum distance back to s
dij_cyc(G,s)
  for u in V
    dist(u) = ∞
                   //makequeue returns a priority queue of all V
  H = makequeue(V) //using dist-values as keys with s First In
  while !H.empty?
    u = deletemin(H)
    for all edges (u,v) in E
      if dist(v) > dist(u) + l(u,v) then
        dist(v) = dist(u) + l(u,v)
        decreasekey(H,v)

  return dist(s)

This runs a slightly different Dijkstra's on each vertex. The mutated Dijkstras has a few key differences. First, all initial distances are set to ∞, even the start vertex. Second, the start vertex must be put on the queue first to make sure it comes off first since they all have the same priority. Finally, the mutated Dijkstras returns the distance back to the start node. If there was no path back to the start vertex the distance remains ∞. The minimum of all these returns from the mutated Dijkstras is the shortest path. Since Dijkstras runs at worst in O(|V|^2) and min_cycle runs this form of Dijkstras |V| times, the final running time to find the shortest cycle is O(|V|^3). If min_cyc returns ∞ then the graph is acyclic.

这在每个顶点上运行略微不同的Dijkstra。变异的Dijkstras有一些关键的区别。首先,所有初始距离都设置为∞,甚至是起始顶点。其次,必须首先将起始顶点放在队列中,以确保它首先脱离,因为它们都具有相同的优先级。最后,变异的Dijkstras将距离返回到起始节点。如果没有返回到起始顶点的路径,则距离保持为∞。来自变异Dijkstras的所有这些返回的最小值是最短路径。由于Dijkstras在O(| V | ^ 2)中运行最差,而min_cycle运行这种形式的Dijkstras | V |次,找到最短周期的最终运行时间是O(| V | ^ 3)。如果min_cyc返回∞则图表是非循环的。

To return the actual path of the shortest cycle only slight modifications need to be made.

要返回最短周期的实际路径,只需要进行微小的修改。

#3


In the unweighted case: Breadth first search. In the weighted case: Dijkstra's.

在未加权的情况下:广度优先搜索。在加权的情况下:Dijkstra的。

#4


For non weighted graph, BFS will do the job. Since there is potential cycle in your graph, you need to keep track of visited node (you sort of need to do this for BFS anyway).

对于非加权图,BFS将完成这项工作。由于图表中存在潜在的循环,因此您需要跟踪被访问节点(无论如何,您需要为BFS执行此操作)。

For weighted graph, bellman–Ford algorithm can be used. It is also able to detect cycles.

对于加权图,可以使用bellman-Ford算法。它还能够检测周期。

#1


EDIT: Oops, misread the question. Thanks @jfclavette for picking this up. Old answer is at the end.

编辑:哎呀,误读了这个问题。谢谢@jfclavette选择了这个。老答案就在最后。

The problem you're trying to solve is called the Travelling salesman problem. There are many potential solutions, but it's NP-complete so you won't be able to solve for large graphs.

您尝试解决的问题称为旅行商问题。有许多潜在的解决方案,但它是NP完全的,所以你将无法解决大型图形。

Old answer:

What you're trying to find is called the girth of a graph. It can be solved by setting the distances from a node to itself to infinity and using the Floyd-Warshall algorithm. The length of the shortest cycle from node i is then just the entry in position ii.

你想要找到的东西叫做图的周长。它可以通过设置从节点到自身的距离到无穷大并使用Floyd-Warshall算法来解决。从节点i开始的最短周期的长度就是位置ii的条目。

#2


In Pseudocode:

//INPUT: graph G = (V,E)
//OUTPUT: shortest cycle length
min_cycle(G)
  min = ∞
  for u in V
    len = dij_cyc(G,u)
    if min > len
      min = len
  return min    

//INPUT: graph G and vertex s
//OUTPUT: minimum distance back to s
dij_cyc(G,s)
  for u in V
    dist(u) = ∞
                   //makequeue returns a priority queue of all V
  H = makequeue(V) //using dist-values as keys with s First In
  while !H.empty?
    u = deletemin(H)
    for all edges (u,v) in E
      if dist(v) > dist(u) + l(u,v) then
        dist(v) = dist(u) + l(u,v)
        decreasekey(H,v)

  return dist(s)

This runs a slightly different Dijkstra's on each vertex. The mutated Dijkstras has a few key differences. First, all initial distances are set to ∞, even the start vertex. Second, the start vertex must be put on the queue first to make sure it comes off first since they all have the same priority. Finally, the mutated Dijkstras returns the distance back to the start node. If there was no path back to the start vertex the distance remains ∞. The minimum of all these returns from the mutated Dijkstras is the shortest path. Since Dijkstras runs at worst in O(|V|^2) and min_cycle runs this form of Dijkstras |V| times, the final running time to find the shortest cycle is O(|V|^3). If min_cyc returns ∞ then the graph is acyclic.

这在每个顶点上运行略微不同的Dijkstra。变异的Dijkstras有一些关键的区别。首先,所有初始距离都设置为∞,甚至是起始顶点。其次,必须首先将起始顶点放在队列中,以确保它首先脱离,因为它们都具有相同的优先级。最后,变异的Dijkstras将距离返回到起始节点。如果没有返回到起始顶点的路径,则距离保持为∞。来自变异Dijkstras的所有这些返回的最小值是最短路径。由于Dijkstras在O(| V | ^ 2)中运行最差,而min_cycle运行这种形式的Dijkstras | V |次,找到最短周期的最终运行时间是O(| V | ^ 3)。如果min_cyc返回∞则图表是非循环的。

To return the actual path of the shortest cycle only slight modifications need to be made.

要返回最短周期的实际路径,只需要进行微小的修改。

#3


In the unweighted case: Breadth first search. In the weighted case: Dijkstra's.

在未加权的情况下:广度优先搜索。在加权的情况下:Dijkstra的。

#4


For non weighted graph, BFS will do the job. Since there is potential cycle in your graph, you need to keep track of visited node (you sort of need to do this for BFS anyway).

对于非加权图,BFS将完成这项工作。由于图表中存在潜在的循环,因此您需要跟踪被访问节点(无论如何,您需要为BFS执行此操作)。

For weighted graph, bellman–Ford algorithm can be used. It is also able to detect cycles.

对于加权图,可以使用bellman-Ford算法。它还能够检测周期。