📜  门| GATE CS 2012 |问题2(1)

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

门 | GATE CS 2012 |问题2

该问题涉及有向无环图(DAG)。

问题描述

给定一个DAG,图中每个结点都有一个权重整数。在该图中,从源到汇的每个路径都有一个权重等于它包含的所有边的权重之和。从所有的路径中选择一条具有最大的权重和。设计并分析一个有效的算法来执行此操作。

解决方案

我们将执行以下步骤来解决这个问题:

  1. 初始化最大权重的路径和为0。

  2. 为了找到从源到汇的路径,我们需要执行一个拓扑排序。

  3. 根据拓扑排序的次序,对于每个结点v,计算从源到结点v的最大权重路径。这样可以通过对所有入边的实际加权和计算出结点v的权重。为达到这个目的,我们需要执行以下操作:

    • 初始化v的最大权重路径和为0。

    • 对于v的每个入边(u,v),计算(u的最大权重路径和)+u到v边的权重,并将这个值与v的最大权重路径和相比较。如果前者更大,就将前者保存为v的最大权重路径和。

  4. 最后,我们从源到汇的最大权重路径就是汇的最大权重路径。

复杂度分析

该算法需要执行一次拓扑排序,这需要O(V+E)的时间复杂度。对于每个结点,我们需要查找它的入边以计算它的最大权重路径。这时,每个结点的入度最多为V-1,所以总体运行时间为O(V(V+E))。罕见情况下,如果图形成基本森林,则每个连通分量都是DAG,计算最大权重路径的运行时间为O(V(E+V))。

代码实现

下面的Python代码实现了上述算法:

from collections import defaultdict

def max_weight_path(graph, source, sink):
    topological_order = []

    indegree = {u: 0 for u in graph}
    for u in graph:
        for v, weight in graph[u]:
            indegree[v] += 1

    queue = [u for u in graph if indegree[u] == 0]

    while queue:
        u = queue.pop(0)
        topological_order.append(u)
        for v, weight in graph[u]:
            indegree[v] -= 1
            if indegree[v] == 0:
                queue.append(v)

    max_weights = {u: float("-inf") for u in graph}
    max_weights[source] = 0

    for u in topological_order:
        for v, weight in graph[u]:
            max_weights[v] = max(max_weights[v], max_weights[u] + weight)

    return max_weights[sink]

# example usage
graph = defaultdict(list)
graph[1] = [(2, 3), (3, 2)]
graph[2] = [(3, 1), (4, 4)]
graph[3] = [(4, 2), (5, 3)]
graph[4] = [(5, 2)]
graph[5] = []
print(max_weight_path(graph, 1, 5))  # 9

该代码使用邻接列表实现图形。使用“indegree”字典计算每个节点的入度,使用“queue”列表存储零入度节点,执行拓扑排序,并使用“max_weights”字典计算每个节点的最大权重路径。