我有一张有向图,长这样:
我想找到从起点到终点的最便宜路径,在此路径中橙色虚线表示必须经过的边。
自然的最短路径是: 起点 -> A -> B -> 终点,路径代价=5,但是我们没有经过所有必须的边。
我想要通过通用解决方案找到的路径是:起点 -> A -> B -> C -> D -> B -> 终点,路径代价=7且我们经过了所有必须的边。
大家有什么想法可以实现这种遍历边的需求吗?
我有一张有向图,长这样:
我想找到从起点到终点的最便宜路径,在此路径中橙色虚线表示必须经过的边。
自然的最短路径是: 起点 -> A -> B -> 终点,路径代价=5,但是我们没有经过所有必须的边。
我想要通过通用解决方案找到的路径是:起点 -> A -> B -> C -> D -> B -> 终点,路径代价=7且我们经过了所有必须的边。
大家有什么想法可以实现这种遍历边的需求吗?
第一步是创建另一个图形。此图形将恰好具有F+2个顶点:
要创建此图形,您需要执行以下操作:
构建此图的复杂度为O((F+2)².(E+V).log(V))其中E(分别是原始图中的边缘数(顶点))。
从这一点开始,我们必须在新创建的图形中找到最短的哈密顿路径。不幸的是,这项任务是一个困难的问题。我们没有比探索每种可能性更好的方法。但这并不意味着我们不能聪明地做到这一点。
我们将使用回溯执行搜索。我们可以通过维护两个集合来实现这一点:
在深入算法定义之前,让我们先了解一些主要思路。在新图中,我们除了探索所有可能路径的整个空间以外,别无他法。在每一步,我们都必须做出一个决定:接下来应该选择哪条边?这就导致一系列的决策,直到我们无法再移动或者到达了s。但现在我们需要回头并撤销一些决策,看看是否可以通过改变方向来做得更好。为了取消决策,我们按照以下步骤进行:
最终算法可以概括为以下方式:(我提供了一种迭代实现,大家可以找到稍微更容易、更清晰一些的递归实现)
令K
← []
,L[0..R+1]
← []
和U
← V(其中V是工作图中每个顶点减去起始和结束顶点t和s的集合)。最后让l
←i
←0和best_path_length
←∞和best_path
←[]
当(i
≥ 0)时:
U
不等于 []
时
c
← U.popFront()
(我们取出 U
的头部)L[i].pushBack(c)
i == R+1
并且 (l
等于 cur_path.back()
到 s 的距离加上 l
) 小于 best_path_length
:
best_path_length
← l
best_path
← cur_path
K.tail()
和 c
之间有一条边 e,并且 weight(e)
+ l
小于 best_path_length
:(如果 K
是空的,则在上述语句中将 K.tail()
替换为 t)
K.pushBack(c)
i
← i
+1l
← weight(e)
+ l
cur_path.pushBack(c)
L[i]
连接到 U
的末尾L[i]
← []
i
← i
-1cur_path.popBack()
在 while 循环的末尾(while (i ≥ 0)
),best_path
将保存最佳路径(在新图中)。从那里,您只需要获取边上的负载以在原始图中重建路径。