图中的最短部分路径
Posted
技术标签:
【中文标题】图中的最短部分路径【英文标题】:Shortest Partial Path in a Graph 【发布时间】:2014-04-20 07:12:33 【问题描述】:我有一个由矩阵定义的网络,其中矩阵中的 [i,j] 元素是从节点 i 到节点 j 的成本。如果 i 和 j 之间没有路径,则 [i,j] 是无限的。
我用负值填充矩阵,所以如果 i 和 j 之间的距离很短,那么我在 [i,j] 中输入非常小的值,例如 -50,如果距离很长,我把更大值,例如 -5。
我想知道如何在网络中找到部分最短路径,唯一的限制是路径应该按照预定义的顺序排列,就像矩阵 i,i+1,i+2,..中出现的元素一样。
举个简单的例子,
╔═══╦═══╦═════╦═══╦═══╦═════╗
║ ║ 1 ║ 2 ║ 3 ║ 4 ║ 5 ║
╠═══╬═══╬═════╬═══╬═══╬═════╣
║ 1 ║ 0 ║ -20 ║ ║ ║ -10 ║
║ 2 ║ ║ 0 ║ ║ ║ ║
║ 3 ║ ║ ║ 0 ║ ║ ║
║ 4 ║ ║ ║ ║ 0 ║ -50 ║
║ 5 ║ ║ ║ ║ ║ ║
╚═══╩═══╩═════╩═══╩═══╩═════╝
这里,完整的路径形式 1-to-5 等于 -10,但是如果我们采用路径 1-to-2 然后 4-to-5 我们得到更好的分数 -50,所以这里我们跳过了 3 就可以了对于部分路径。
因此,部分路径 - 是不必访问每个节点的路径,它可能只是 1 到 2 的短段,但最短的部分路径必须是所有部分路径中最短的。
关于顺序的约束很简单,我们总是从节点1开始搜索路径并按升序进行,所以对于路径中的所有段[i,j] [i1,j1],j>i和i1> =j。
不知道有没有什么好的方法可以在网络中找到最好的部分路径,我觉得穷举搜索也是不错的解决方案,节点数在15-20左右。
【问题讨论】:
所以,你可以从节点i
移动到节点j
,只有当i<j
?
另外,定义“部分最短路径”的含义
我想我还是遗漏了一些东西,在这种情况下,最短路径不就是(u,v)
,用于使用权重最低的边吗?
@amit,是的,但是权重是负数,所以我们倾向于聚合尽可能多的细分。
【参考方案1】:
您基本上在这里有一个Directed Acyclic Graph (DAG),并且您正在寻找其中最长的路径,根据w(u,v)
- 其中w(u,v)
是每个连接(边缘)的正权重.如果u
到v
之间没有边,我们将其权重表示为负无穷:w(u,v)=-infinity
。
图表是G=(V,E)
,其中V
是一个包含所有节点的集合,E = (u,v,w(u,v) | u<v
是边集合。
一般来说,Longest Path Problem 是 NP-Complete。幸运的是,您的问题是一个 DAG,并且有一个有效的Dynamic Programming 解决方案。先topologically sort节点,然后 - 从最后到第一个:
d(v) = max d(u) + w(v,u) | for all edges (v,u)
完成后,对于每个节点v
d(v) 将表示从该节点开始的最长路径,您只需从中找到最大值即可获得所需的节点和最大值。
您可以稍后通过以下方式重建路径:
v <- startNode //the node just found to be starting the desired path
list <- [v]
while (d(v) != 0):
for each edge (v,u):
if d(v) - w(v,u) == d(u):
list.append(u)
break
return list
【讨论】:
非常感谢您的解决方案,我会尝试实现它,但是看起来它没有考虑跳过节点的情况。 我认为这个解决方案有效,但答案的措辞很奇怪,它看起来像是“偶然”工作的。我认为你会保持边缘权重 negative 并且即使有正权重它也可以工作。如果缺少边,添加权重为 0 的“假”边。然后在重建“部分路径”时,只需删除权重为 0 的任何边(请注意,如果边碰巧是“真实的”,则不在乎它是否被删除因为你仍然有一个“部分路径”)。也不需要拓扑排序——它们已经被排序了。只需从右到左构建 DP 表以上是关于图中的最短部分路径的主要内容,如果未能解决你的问题,请参考以下文章