📜  门| GATE CS 2021 |套装2 |问题6(1)

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

门| GATE CS 2021 | 套装2 | 问题6

这是一个有关于GATE CS 2021套装2中问题6的介绍。这个问题需要程序员设计一个算法,并使用Python语言实现,在给定的有向无环图中找到最长路径。以下是一个详细的介绍。

问题描述

给定一个有向无环图(DAG),图的节点用整数a, a+1, a+2, …… b表示,其中a和b是给定的整数。图中的每个节点都具有一个权值,这些权值存储在权重数组W(W [i]是节点i的权重)中。从a到b的最长路径是什么?

请注意,路径的权值是该路径上所有边的权值之和。

算法设计

要解决这个问题,可以使用动态规划算法。该算法需要遍历每个节点,并根据该节点的前驱节点计算最长路径。在此过程中,可以使用一个列表L,其中L [i]存储从a到节点i的最长路径。然后,可以使用以下递归公式计算L [i]的值:

L[i] = max(W[i] + L[j] | j ∈ G, (j,i)∈E)

其中,G是图中所有节点的集合,E是图中所有边的集合,符号“|”表示在给定条件的情况下具有某种属性的元素的集合。

这个递归公式可以被理解为:从a到i的最长路径,是从a到i的每个前驱节点j(存在(j,i)∈E),加上从j到i的路径权值W [i]之后的最长路径中的最大值。

当然,对于L [a],它只是它自己的权重W [a],因为没有来自其他节点的边。

最终的解,是L [b],因为这是从a到b的最长路径。

Python实现

下面是该算法的Python实现,其中涉及到了图的构造,可以按照题目要求进行构造。

def longest_path(a, b, W, G):
    n = b - a + 1
    L = [(0, 0)] * n
    L[0] = (W[a], a)
    for i in range(1, n):
        max_pred = -1
        max_weight = -1
        for j in range(i):
            if G[j][i] > 0 and L[j][0] > max_weight:
                max_pred = j
                max_weight = L[j][0]
        if max_pred >= 0:
            L[i] = (max_weight + W[a+i], a+max_pred)
        else:
            L[i] = (W[a+i], a+i)
    return L[-1]

# example usage
a = 2
b = 8
W = [0, 3, 4, 8, 6, 1, 5, 2, 7] # node 0 is unused
G = [[0,0,0,0,0,0,0,0,0],
     [0,0,1,0,0,0,0,0,0],
     [0,0,0,1,0,0,0,0,0],
     [0,0,0,0,1,1,0,0,0],
     [0,0,0,0,0,0,1,0,0],
     [0,0,0,0,0,0,1,1,0],
     [0,0,0,0,0,0,0,1,1],
     [0,0,0,0,0,0,0,0,1],
     [0,0,0,0,0,0,0,0,0]]

result = longest_path(a, b, W, G)
print("Longest path from", a, "to", b, "is from node", result[1], "with weight", result[0])

这个Python实现使用了一个nxn的邻接矩阵G,其中n = b-a+1是图中节点的数量。如果存在一条从节点i到节点j的有向边,则G [i] [j] = 1,否则G [i] [j] = 0。

该实现返回从a到b的最长路径长度和它的末尾节点的编号。由于adj中节点从1开始,而不是0,因此需要在索引节点时将a加到节点编号中。