📌  相关文章
📜  有向无环图给出的每个作业完成所需的最短时间(1)

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

有向无环图(DAG)中的作业最短时间问题

在工程、制造、计算机科学等领域中,经常需要确定完成任务的最短时间。如果任务之间存在依赖关系,那么可以将任务及其依赖组成一个有向无环图(DAG),然后利用拓扑排序和动态规划等算法求解每个任务的最短时间。

问题描述

假设有n个任务,每个任务需要一定的时间才能完成。另外,有一些任务之间存在依赖关系,即某些任务必须先于另外一些任务完成。例如,任务A必须在任务B完成之前完成,可以表示为A->B。现在需要通过求解最短时间,确定各个任务的执行顺序,使得所有任务都能按照要求被完成。

解决方法
拓扑排序

首先需要将DAG转化为有序的任务序列。这个过程可以通过拓扑排序来完成。对于每个任务,计算它的入度(即它前面有多少个任务),然后从入度为0的任务开始,不断删除该任务以及其相关的边,直到所有任务都被删除为止。这个过程中产生的任务序列即为所求。

拓扑排序的时间复杂度为O(n+m),其中n为任务数,m为边数。

动态规划

接下来,需要确定每个任务最短需要多少时间才能完成。这个过程可以通过动态规划来完成。假设t[i]表示第i个任务最短需要多少时间才能完成,w[i]表示第i个任务需要的时间,p[i]表示第i个任务的前驱任务集合。则有:

t[i] = max{t[j]+w[i]},其中j∈p[i]。

即第i个任务的最短时间是其所有前驱任务的最短时间+自身需要的时间的最大值。由此可以递归地计算出所有任务的最短时间,从而得到每个任务的最短时间和任务序列。

动态规划的时间复杂度为O(n+m),与拓扑排序相同。

代码实现

以下是Python实现的示例代码,假设输入为一个有向无环图的邻接表(adjList)和每个任务需要的时间列表(w):

def topologicalSort(adjList, w):
  n = len(w)
  inDegree = [0]*n
  for u in range(n):
    for v in adjList[u]:
      inDegree[v] += 1
  q = [u for u in range(n) if inDegree[u] == 0]
  order = []
  while q:
    u = q.pop(0)
    order.append(u)
    for v in adjList[u]:
      inDegree[v] -= 1
      if inDegree[v] == 0:
        q.append(v)
  return order

def shortestTime(adjList, w):
  n = len(w)
  order = topologicalSort(adjList, w)
  t = [0]*n
  for u in order:
    t[u] = max([t[v]+w[u] for v in adjList[u]], default=0)
  return t, order

以上代码的时间复杂度为O(n+m),其中n为任务数,m为边数。