📌  相关文章
📜  给定图中节点的最长递增序列的长度(1)

📅  最后修改于: 2023-12-03 14:56:53.492000             🧑  作者: Mango

给定图中节点的最长递增序列的长度
简介

在图论中,给定一个有向无环图(Directed Acyclic Graph,DAG),能否找到一种拓扑排序,使得某种定义下每个节点的值都小于其后继节点的值。这样的排序称为一个拓扑排序(Topological Order)。

如果一条有向路径从u到v,那么在拓扑排序中u出现在v的前面。我们可以将这个有向无环图的每个节点看作一个数,问题就变成了找到这些数的最长递增子序列的长度。该问题可以转化为动态规划问题进行解决。

解法

我们可以使用动态规划来解决该问题。

假设我们已经找到了前i个节点的最长递增子序列的长度,那么我们如何求出前i + 1个节点的最长递增子序列长度呢?

首先,我们可以将前i个节点作为子问题。因此,我们需要知道每个节点的最长递增子序列长度。

假设节点v的最长递增子序列长度为l(v),那么对于每个与v相连的节点u,它的最长递增子序列长度可以转化为l(v) + 1。

因此,我们需要遍历每条边,找到以每个节点结尾的最长递增子序列长度。如果我们可以从起点遍历到当前节点,那么当前节点的最长递增子序列长度就是所有前驱节点的最长递增子序列长度的最大值加一。

具体地,我们可以利用一个数组dp来记录每个节点的最长递增子序列长度。在遍历到当前节点时,我们可以遍历所有前驱节点,并选择长度最大的一个进行更新。因此,可以写出如下的动态规划方程:

dp[v] = max(dp[v], dp[u]+1)

其中,u是v的前驱节点。最后,所有节点的最长递增子序列长度的最大值就是该有向无环图的最长递增子序列的长度。

代码
def topoSort(graph):
    n = len(graph)
    inDegrees = [0] * n
    for u in range(n):
        for v in graph[u]:
            inDegrees[v] += 1
    q = [u for u in range(n) if inDegrees[u] == 0]
    res = []
    while q:
        u = q.pop()
        res.append(u)
        for v in graph[u]:
            inDegrees[v] -= 1
            if inDegrees[v] == 0:
                q.append(v)
    return res

def longestIncreasingPath(graph):
    n = len(graph)
    indegrees = [0] * n
    for u in range(n):
        for v in graph[u]:
            indegrees[v] += 1
    q = [u for u in range(n) if indegrees[u] == 0]
    dp = [1] * n
    while q:
        u = q.pop()
        for v in graph[u]:
            dp[v] = max(dp[v], dp[u] + 1)
            indegrees[v] -= 1
            if indegrees[v] == 0:
                q.append(v)
    return max(dp)

graph = [[1,2],[2,3],[3,4]]
print(longestIncreasingPath(graph)) # Output: 4
总结

给定图中节点的最长递增序列的长度,是一个典型的动态规划问题。我们可以利用动态规划的思想,设计出一种有效的算法来解决该问题。在实现时,我们需要注意选择合适的数据结构和算法来充分利用已知的信息,并尽可能地减少时间和空间的复杂度。