📌  相关文章
📜  教资会网络 | UGC-NET CS 2017 年 12 月 2 日 |问题 28(1)

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

UGC-NET CS 2017 年 12 月 2 日 | 问题 28

这道问题要求求出一个有向无环图中,从源点到汇点的最长路径长度。这里介绍两种算法,一种是基于拓扑排序的动态规划算法,另一种是基于Dijkstra算法的优化算法。

基于拓扑排序的动态规划算法

我们先对有向无环图进行拓扑排序,得到拓扑序列。我们从源点出发,依次对每个节点进行以下操作:

  1. 如果节点没有入度,将其入队;
  2. 对队列中的节点,对其所有出边进行更新,即更新其所有后继节点的最长路径;
  3. 将所有被更新的节点入队。

最后,在最长路径数组中找到汇点对应的路径长度即可。具体实现可以参考下面的代码片段。

from collections import deque

def longest_path(n, edges, start, end):
    # 初始化邻接矩阵和入度数组
    graph = [[0] * n for _ in range(n)]
    in_degrees = [0] * n
    for u, v, w in edges:
        graph[u][v] = w
        in_degrees[v] += 1

    # 拓扑排序,初始化队列
    queue = deque()
    for i in range(n):
        if in_degrees[i] == 0:
            queue.append(i)
    
    # 动态规划
    longest_paths = [-float('inf')] * n
    longest_paths[start] = 0
    while queue:
        u = queue.popleft()
        for v in range(n):
            if graph[u][v] > 0: # u到v有边
                in_degrees[v] -= 1
                longest_paths[v] = max(longest_paths[v], longest_paths[u] + graph[u][v])
                if in_degrees[v] == 0:
                    queue.append(v)

    return longest_paths[end]
基于Dijkstra算法的优化算法

我们可以将Dijkstra算法进行修改,使其适用于有向图,即每次更新节点的所有后继节点。具体实现可以参考下面的代码片段。这个算法的时间复杂度为$O(E + VlogV)$,其中E是边数,V是节点数。

import heapq

def longest_path(n, edges, start, end):
    # 初始化邻接矩阵和入度数组
    graph = [[] for _ in range(n)]
    in_degrees = [0] * n
    for u, v, w in edges:
        graph[u].append((v, w))
        in_degrees[v] += 1

    # 拓扑排序,初始化队列
    queue = []
    for i in range(n):
        if in_degrees[i] == 0:
            heapq.heappush(queue, (0, i))
    
    # Dijkstra算法
    longest_paths = [-float('inf')] * n
    longest_paths[start] = 0
    while queue:
        length, u = heapq.heappop(queue)
        for v, w in graph[u]:
            in_degrees[v] -= 1
            longest_paths[v] = max(longest_paths[v], longest_paths[u] + w)
            if in_degrees[v] == 0:
                heapq.heappush(queue, (-longest_paths[v], v))

    return longest_paths[end]

以上两种算法都可以求出最长路径长度,具体选用哪种算法可以根据实际情况进行选择。