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

📅  最后修改于: 2023-12-03 15:42:12.644000             🧑  作者: Mango

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

本题是2021年GATE计算机科学考试的一个问题。它涉及到解决带权重重名有向无环图(DAG)的最长路径问题。 在本文中,我们将讨论如何解决这个问题。

问题描述

给定一个带权重重名有向无环图(DAG),每个节点都有一个权重和一个名称。在DAG中,有多个节点可能会具有相同的名称,但是每个节点都有唯一的权重。 现在,您需要找到其最长路径,该路径的长度为所有访问的节点的权重之和。 请注意,您不能重复访问任何节点。

例如,考虑下面的DAG:

     2        3
   A ----> B ----> C
   | 10           | 5
   v              v
   D ----> E ----> F
        1         1

在这个例子中,最长路径是A -> B -> C,长度是10+3+5=18。

解决方案

解决该问题的一个流行方法是使用拓扑排序和动态规划。 让我们看一下如何解决该问题。

第一步:拓扑排序

由于我们的DAG是无环的,因此我们可以使用拓扑排序将节点排序并找到其拓扑顺序。 拓扑排序通常在O(V+E)时间内进行,其中V是节点数,E是边数。 在拓扑排序的过程中,我们将每个节点标记为“visited”一次,以确保我们不会重复访问任何节点。

第二步:动态规划

一旦我们获得了DAG的拓扑排序,我们就可以使用动态规划尝试找到最长路径。 我们将节点u的最长路径表示为L(u),那么对于DAG的任何节点u,其最长路径L(u)应该是其前面节点中任何一个节点v的最长路径加上从v到u的边的权重,即:

L(u) = max(L(v) + weight(v,u))

在这个式子中,weight(v,u)是从节点v到节点u的边的权重。

第三步:计算最长路径

当我们为所有用拓扑排序排列的节点计算L(u)时,我们可以找到DAG的最长路径。 我们只需要在所有L(u)中选择最大值,即:

max(L(u))
代码实现

下面是一个Python代码片段,用于解决带权重重名有向无环图的最长路径问题:

from collections import defaultdict
  
class Graph:
    def __init__(self, vertices):
        self.V = vertices # No. of vertices
        self.graph = defaultdict(list)
  
    # function to add an edge to the graph
    def addEdge(self, u, v, w):
        self.graph[u].append((v, w))
  
    # A recursive function to implement topologicalSort
    def topologicalSortUtil(self, v, visited, stack):
  
        # Mark the current node as visited
        visited[v] = True
  
        # Recur for all the vertices adjacent to this vertex
        if v in self.graph.keys():
            for node, weight in self.graph[v]:
                if visited[node] == False:
                    self.topologicalSortUtil(node, visited, stack)
  
        # Push current vertex to stack which stores the result
        stack.append(v)
  
    # The function to find the longest path in the graph
    def longestPath(self, s):
        # Step 1: Create a list to store indegrees of all
        # vertices. Initialize all indegrees as 0.
        in_degree = [0]*(self.V)
  
        # Traverse adjacency lists to fill indegrees of
        # vertices. This step takes O(V+E) time
        for u in self.graph.keys():
            for v, w in self.graph[u]:
                in_degree[v] += 1
  
        # Step 2: Create a stack and push all vertices with
        # indegree 0 to the stack.
        stack = []
        visited = [False]*(self.V)
        for i in range(self.V):
            if in_degree[i] == 0 and not visited[i]:
                self.topologicalSortUtil(i, visited, stack)
  
        # Step 3: Initialize distances to all vertices as
        # minus infinite and distance to source as 0
        dist = [-float("inf")]*(self.V)
        dist[s] = 0
  
        # Step 4: Process vertices in topological order i.e.
        # in order by which we obtained stack
        while stack:
  
            # Get the next vertex from topological order
            u = stack.pop()
  
            # Update distances of all adjacent vertices
            for v, w in self.graph[u]:
                # Relax the edge
                if dist[v] < dist[u] + w:
                    dist[v] = dist[u] + w
  
        # Step 5: Return the longest path
        return max(dist)

# Driver program to test above functions
g = Graph(6)
g.addEdge(0, 1, 2)
g.addEdge(0, 3, 10)
g.addEdge(1, 2, 3)
g.addEdge(3, 4, 1)
g.addEdge(4, 2, 1)
g.addEdge(2, 5, 5)
print(g.longestPath(0)) # Output: 18

在这个代码片段中,我们创建了一个Graph类,使用defaultdict将节点名称映射到其相邻节点及其权重的列表上。我们还实现了topologicalSortUtil()longestPath()方法来实现上述算法。 最后,我们使用一个例子来测试代码,输出最长路径的长度:18。

结论

在本文中,我们已经介绍了如何解决带权重重名有向无环图的最长路径问题。我们使用了拓扑排序和动态规划技术,并展示了一个Python实现。 我们希望该指南对您解决这个问题有所帮助。