Algorithm 如何在无权一般图的所有简单路径中找到最长的增长子序列?

Algorithm 如何在无权一般图的所有简单路径中找到最长的增长子序列?,algorithm,graph,dynamic-programming,lis,Algorithm,Graph,Dynamic Programming,Lis,设G=(V,E)是一个无权一般图,其中每个顶点V都有权w(V) G中简单路径p的递增子序列是一个p的顶点序列,其中沿该序列的所有顶点的权重都增加。简单路径可以是闭合路径 简单路径p的最长递增子序列(LIS)是具有最大顶点数的p的递增子序列 问题是,如何在G的所有简单路径中找到最长的递增子序列 请注意,图是无向的,因此它不是有向无环图(DAG)。这里有一个非常快速的算法来解决这个问题。图中最长的递增子序列是图中路径的子序列,每条路径必须完全属于单个连接组件。因此,如果我们可以在连接的组件上解决这个

G=(V,E)是一个无权一般图,其中每个顶点V都有权w(V)

G中简单路径p的递增子序列是一个p的顶点序列,其中沿该序列的所有顶点的权重都增加。简单路径可以是闭合路径

简单路径p的最长递增子序列(LIS)是具有最大顶点数的p的递增子序列

问题是,如何在G的所有简单路径中找到最长的递增子序列


请注意,图是无向的,因此它不是有向无环图(DAG)。

这里有一个非常快速的算法来解决这个问题。图中最长的递增子序列是图中路径的子序列,每条路径必须完全属于单个连接组件。因此,如果我们可以在连接的组件上解决这个问题,我们可以通过在所有连接的组件上找到最佳解决方案来解决整个图的问题

接下来,考虑一个例子,你正在解决一个连通图G的这个问题。在这种情况下,你能找到的最长的递增子序列是通过按节点的权重排序,然后从最小权重节点遍历到第二个,然后遍历到第三个,然后遍历到第四个,等等。如果有任何关联或重复,你可以跳过它们。换句话说,你可以通过

  • 按权重对所有节点进行排序
  • 丢弃每个权重中除一个节点外的所有节点,以及
  • 通过依次访问每个节点来形成LIS
  • 这将导致对整个问题的快速算法。在时间O(m+n)中,查找所有连接的组件。对于每个连接的组件,在时间O(Sort(n))中使用前面的算法,其中Sort(n)是对n个元素进行排序所需的时间(如果使用heapsort,可以是Θ(n logn),Θ(n+U)用于桶排序,Θ(n lgu)用于基数排序,等等)。然后,返回找到的最长序列

    总的来说,运行时是O(m+n+&Sort(n)),这比我以前的方法好,应该更容易编写代码


    我最初发布了这个答案,因为我觉得它很有趣,所以我将其保留:

    假设您从图G中选择了一条简单的路径,并查看该路径的最长递增子序列。尽管路径遍历整个图,并且可能有许多中间节点,但该路径的最长递增子序列实际上只关心

    • 路径上的第一个节点也是LIS的一部分
    • 从该点开始,路径中的下一个最大值
    因此,我们可以考虑像这样形成一个LIS。从图中的任意节点开始。现在,移动到图中(1)的值高于当前节点且(2)可从当前节点访问的任何节点,然后根据需要重复此过程。目标是以一种提供尽可能长的递增值序列的方式进行

    我们可以将此过程建模为在DAG中查找最长路径。DAG中的每个节点表示原始图G中的一个节点,并且从节点u到节点v有一条边(如果有)

    • 在G中有一条从u到v的路径
    • w(u)
    这是一个DAG,因为第二个条件,即使原始图形不是DAG

    因此,我们可以通过两个步骤来解决这个总体问题。首先,构建上面描述的DAG。为此:

  • 找到原始图G的连接组件,并用其连接组件编号标记每个节点。时间:O(m+n)

  • 对于G中的每个节点u,在新的DAG D中构造一个对应的节点u'。时间:O(n)

  • 对于G中的每个节点u,以及与u位于同一SCC中的每个节点v,如果w(u)
  • 求D中的最长路径。该路径对应于G中任何简单路径的最长递增子序列。时间:O(m+n)

  • 总体运行时间:最坏情况下为Θ(n2),最佳情况下为Θ(m+n)