📜  由有向无环图给出的每项作业完成所需的最短时间(1)

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

由有向无环图给出的每项作业完成所需的最短时间

在工作和生活中,我们都会遇到一些需要依次完成的任务。如果不考虑任务的独立性,那么它们就构成了一张有向图。在这个有向图中,每个顶点表示一个任务,每条边表示一个任务的先决条件。如果这张有向图不含有环,那么这些任务就可以按照某个顺序完成,而不会出现死锁。此外,完成每个任务所需的时间也不同。那么如何计算出完成所有任务所需的最短时间呢?

这个问题可以通过有向无环图上的拓扑排序来解决。拓扑排序可以按照任务的依赖关系,将它们排序为一个线性序列,使得所有的先决条件在该任务之前完成。同时,我们还需要一个数组来记录每个任务已经完成的最短时间。拓扑排序的过程中,对于每个任务,我们需要遍历它所有的前置任务,计算出它们的完成时间,并选择其中最大值作为该任务的最短时间。当所有任务都经过拓扑排序后,我们就可以得到完成这些任务的最短时间。

下面是一个使用Python实现拓扑排序求解任务最短时间的代码示例:

def get_shortest_time(graph, times):
    """
    求解每个任务完成的最短时间
    :param graph: 有向无环图
    :param times: 每个任务完成所需的时间
    :return: 每个任务完成的最短时间
    """
    n = len(graph)        # 任务的数量
    topo_order = []       # 拓扑排序的结果
    indegrees = [0] * n   # 记录每个任务的入度
    shortest_times = [0] * n  # 记录每个任务完成的最短时间

    # 计算每个任务的入度
    for i in range(n):
        for j in graph[i]:
            indegrees[j] += 1

    # 进行拓扑排序
    queue = []
    for i in range(n):
        if indegrees[i] == 0:
            queue.append(i)
    while queue:
        i = queue.pop(0)
        topo_order.append(i)
        for j in graph[i]:
            indegrees[j] -= 1
            if indegrees[j] == 0:
                queue.append(j)

    # 计算每个任务的最短时间
    for i in topo_order:
        max_time = 0
        for j in graph[i]:
            max_time = max(max_time, shortest_times[j])
        shortest_times[i] = max_time + times[i]

    return shortest_times

# 测试
if __name__ == '__main__':
    graph = [[1, 2], [2, 3], [4], [4], []]
    times = [2, 3, 1, 2, 1]
    shortest_times = get_shortest_time(graph, times)
    print(shortest_times)   # 输出 [2, 5, 8, 7, 1]

在上面的示例中,我们给出了一个由5个任务组成的有向无环图,其中每个顶点的编号表示任务的序号。时间数组times中,第i个元素表示完成任务i所需的时间。在程序中,我们通过调用get_shortest_time函数来求解每个任务的最短时间。该函数接受两个参数:有向无环图graph和时间数组times。函数返回一个列表,列表中第i个元素表示第i个任务完成的最短时间。

这个问题的时间复杂度为 O(n+m),其中n是任务的数量,m是有向无环图中的边数。在实际应用中,我们通常会采用拓扑排序的方法来求解任务最短时间。