来自一个源的最短路径穿过N个边缘

时间:2018-06-29 09:59:22

标签: algorithm optimization graph shortest-path

在我的经济学研究中,我目前正在处理一个特定的最短路径问题:

给定有向权重的确定性动态图,在边缘上,我需要找到一个源S的最短路径,该路径穿过N条边缘。该图可以具有周期,边缘权重可以为负,并且路径可以多次通过顶点或边缘。

是否有解决此问题的有效算法?

2 个答案:

答案 0 :(得分:1)

一种可能性是:

首先找到图中最低的边缘权重。

,然后建立一个从起始边缘开始的所有路径的优先级队列(最初是从起始点开始的空路径),在该队列中,所有尚未处理的边缘都被认为具有最低权重。

主循环:

  1. 从队列中删除权重最低的路径。
  2. 如果路径具有N条边,则操作完成
  3. 否则,将该路径的所有可能的单边扩展添加到优先级队列

但是,这种简单的算法有一个缺陷-您可能会以第i个边缘的形式多次访问顶点(访问第2个和第4个边缘是可以的,但是在两个不同的路径中访问第4个是可以的),这效率很低。

可以通过在上面的第3步中跳过它们来改进算法,因为优先级队列可确保到达顶点的第一部分路径的权重和最低,而其余路径不依赖于您到达顶点的方式(因为可以复制边和顶点)。

答案 1 :(得分:0)

“完全N边”约束使此问题比不存在该约束容易得多。从本质上讲,您可以求解N = 0(仅是起始节点),使用它来求解N = 1(起始节点的所有邻居),然后求解N = 2(解决方案的邻节点N = 1,采用成本最低的路径)对于连接到多个节点的节点),等等。

在伪代码中(使用{field: val}表示“具有值为field的名为val的字段的记录”)

# returns a map from node to cost, where each key represents 
# a node reachable from start_node in exactly n steps, and the
# associated value is the total cost of the cheapest path to 
# that node
cheapest_path(n, start_node):
  i = 0
  horizon = new map()
  horizon[start_node] = {cost: 0, path: []}
  while i <= n:
    next_horizon = new map()
    for node, entry in key_value_pairs(horizon):
      for neighbor in neighbors(node):
        this_neighbor_cost = entry.cost + edge_weight(node, neighbor, i)
        this_neighbor_path = entry.path + [neighbor]
        if next_horizon[neighbor] does not exist or this_neighbor_cost < next_horizon[neighbor].cost:
          next_horizon[neighbor] = {cost: this_neighbor_cost, path: this_neighbor_path}
    i = i + 1
    horizon = next_horizon
  return horizon

我们考虑使用edge_weight(node, neighbor, i)的动态权重,意思是“在时间node时从neighbori的成本。

这是像Dijkstra算法那样的单源最短路径算法的简并版本,但是它要简单得多,因为我们知道我们必须精确地走N步,所以我们不必担心陷入负重循环中,重量较轻的长路径等等。