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