假设您有一组可以并行完成的作业。每个工作都有时间要求(第i个工作的时间要求是t_i)。还有一些依赖,其中第i个说你必须在工作v_i之前做u_i工作。你必须尽量减少所需的总时间。
通过将这些关系转换为有向非循环图,然后使用它来确定并行执行哪些操作,可以轻松完成。
如果我不清楚,这是一个例子。假设你有5个工作,时间要求分别为2,9,3,12,5,你必须在5之前做3,在5之前做4,在1之前做3之前,然后在1之前做1.然后你能做的最好是17.这是你的dag:
+---> 1 (2) ---> 2(9)
|
3 (3)
|
+----> 5 (5)
^
|
4 (12)-+
你可以并行执行3和4,这样你就可以花费MAX(3,12)= 12个单位的时间来做5,这需要5个单位的时间。因此,在17个单位时间后完成5。另一方面,在14个单元之后完成2。所以答案是17。
问题是,如果每个查询中只更新了一次要求(每次从原始图开始,而不是之前修改后得到的图) 如何有效地找到新的最短时间要求?
对于那些想要约束的人,工作数< = 10 ^ 5。依赖数< = 10 ^ 6,查询数< = 10 ^ 6.
答案 0 :(得分:2)
时间要求是非循环有向图中路径的最大权重。对于每个节点,两个线性时间遍历产生以该节点结束的路径的最大权重以及以该节点开始的路径的最大权重。现在我们可以找到包含指定节点的路径的最大长度。如果节点的权重增加,那么我们取前一个最大值的最大值和涉及该节点的新的最大值,我们可以在恒定时间内计算。
减少是比较棘手的,因为对于最大权重路径中的每个节点,我们需要包含该节点的路径不的最大权重。我能想到的第一种方式(可能不是最好的方法)如下。向非循环有向图添加源和接收器,两者的权重为零,并且连接到(源)或从(接收)每个其他节点。以拓扑顺序对节点编号,其中源为0且接收器为n + 1,并初始化将树节点映射到路径权重的段树,其中初始值为-infinity。此段树具有以下对数时间操作。
Weight(i) - returns the value for node i
Update(i, j, w) - updates the value for nodes i..j to
the maximum of the current value and w
对于从i
到j
的每个弧,请致电Update(i + 1, j - 1, w)
,其中w
是包含从i
到j
的弧的路径的最大权重{{1}}。最后,分段树中的每个权重是除相应节点之外的路径的最大权重。
(关于运行时间的注意事项:通过分别处理没有依赖关系的节点,这种方法的运行时间可以是O(m log n + n + q),其中n是节点数,m是依赖性的数量,q是查询的数量。我的分段树类型是计算3D最大值,这是计算几何学研究得很好的问题。对于预分类输入(至少在二维中),n点的最快已知算法是O (n log log n),通过van Emde Boas树。在某些情况下,还存在比输出敏感时限更好的算法。)