我知道longest path problem对于一般图表来说是NP难的。但是,我正在考虑一种特殊的图形,包括一个周期,加上周期的每个顶点上的一个附加边缘事件。例如,对于长度为7的循环,我们有图表:
所有边都是加权的(权重是实数,可以是正数或负数)。我想在此图上找到最大的简单路径,其中路径的大小是路径上边缘权重的总和。
算法应该是循环大小的线性。但任何想法都值得赞赏。
答案 0 :(得分:5)
这可以减少到Maximum subarray problem并在线性时间内解决。
- >
必要的Kadane算法修改:
N
个或更多“循环”节点时,从尾部修剪节点。要有效地修剪这些节点,我们需要一个可以报告其元素最小值的队列。将元素推送到此队列,无论路径的头部在哪里前进(如果非负,则添加叶边权重),修剪路径尾部时弹出元素,并在将当前路径重置为空路径的位置重置队列。此队列包含前缀长度(不一定是简单的)路径,其中最小值给出了推进路径尾部的正确位置。这样的队列既可以实现为只保留非递减值的双端队列,也可以实现为this回答中提到的一对堆栈。max(0, leaf_edge_weight)
,只要当前路径的长度低于零(而不是像原始Kadane的算法那样将其重置为零)。答案 1 :(得分:0)
最长的路径几乎肯定在两个外顶点之间。几乎肯定有必要覆盖周期中的所有顶点。
因此,您希望使用DFS在O(N)中映射循环。然后计算当前循环排列的长度。添加到该长度的是从循环中的第一个点到它的外部的距离,以及它的外部的最后一个点。这样就可以得到实际的路径长度,它与周期长度分开存储。
增加第一个点和最后一个点的索引(可以在O(1)中完成),移除现在从第一个点到最后一个点的边缘的长度。然后再次添加外部长度。重复,直到覆盖所有顶点。由于您存储和更新路径长度而不是每次实际重新计算(需要(O(N ^ 2)),因此可以在O(N)中完成。
这允许在O(N)中遍历循环。但是,它不是一个精确的算法。这需要检查你不应该使用第一个+ i和/或last-j代替某些i,j。要完全检查,基本上需要O(N ^ 2)。
尽管如此,你可能会在O(N log N)附近巧妙地确定这些边缘情况的可能性。我怀疑是否可以使用精确的线性算法。
答案 2 :(得分:0)
选择循环链接。最长的路径要么经过这个链接,要么不经过这个链接,所以让我们在任何一种情况下找出最佳答案,然后挑选最好的答案。
如果最长路径未通过循环链接,请删除链接以生成树。从离开工作开始,在每个节点处,该节点下的最长路径,以及从该节点到任何后代的最长路径。在每个节点,您可以通过查看其子项的答案来计算答案。根处的答案为您提供了最长的路径。
如果最长路径确实通过您选择的链接,则它必须包含从链接的一端顺时针方向移动的部分和从链接另一端逆时针移动的部分。这两个的长度加起来不超过一个加上构成循环的链接数。对于i = 1,限制从链路每侧的时钟和逆时针路径的成本,并保持运行的最大值。通过链路的最长路径的长度是最长路径的总和,对于某些k,最长路径顺时针方向为最多k个链路,最长路径为逆时针方向,最多为Nk链路(可能有一些相似的成本 - 存在链接成本)。因此,您可以找到通过所选链接的最长路径,费用也为O(n)。
计算两个案例,每个案例的成本为O(n)并且选择最佳成本给出总成本O(n)