添加边缘以指向具有其他限制的非循环图

时间:2009-08-12 11:25:42

标签: graph-theory directed-acyclic-graphs

我有一个DAG。我有这个操作在两个节点之间添加边。

如果A可以从B到达,则B是A的父亲。如果A可以从B到达而不通过另一个节点,则B是A的直接父节点。

此图表的要求是:

  1. 没有周期。
  2. 对于任何节点,有一个直接父亲P [1],P [2],P [3] ...... P [i]的列表对于任何i和j都不是P [j]的父亲。
  3. 如果添加边缘,则不满足要求1,则不构造边。 如果添加边缘,则不满足要求2,则构造边缘,但直接父节点将以满足要求2的方式进行修改。

    例如,有3个节点

    • A,直接父母:无
    • B,直接父母:A
    • C,直接父母:A

    现在,如果我在B和C之间添加边,我们有

    • C,直接父母:A,B

    但A是B的父级,不符合要求2,因此A从C的直接父级中移除,我们有

    • C,直接父母:B

    目前这就是我所做的: 从A到B添加边缘(此A成为B的父级)

    1. BFS检查B是否是A的父母。如果是这样,请不要添加边缘。(这确保没有循环)
    2. 通过BFS检查A是否已经是B的父母。如果是这样,请不要添加边缘。
    3. 找到A的父母与B的直接父母的交集。这是通过找到A虽然BFS的每个父母来完成的。从B的直接父项中删除交集,并添加A作为B的直接父项。(2和3确保它符合要求2)
    4. 这很慢。它在5k节点级别崩溃(我正在寻找这个来处理节点少于100k的任何图形),速度变得不可接受,添加节点边缘为0.02秒。

      我感觉步骤1和2可以通过一些其他算法一步完成。

      我想过使用拓扑排序,但它必须横向整个图形,这是我的第1步和第2步的最坏情况。添加新节点时,排序将中断。所以每次插入时我都要运行拓扑排序,所以它不会产生任何好处。 对于第3步,必须找到整个A的父母。这个过程相当慢,因为它平均横向图的一个不错的部分。

      如何提高效率?

2 个答案:

答案 0 :(得分:4)

你的问题归结为“可以在DAG中插入边缘比O(v + e)快吗?”根据要求(1)。要求(2)是一个更局部的约束,不需要检查整个图形。

我认为答案是否定的:在最坏的情况下你不能比O(v+e)更好(其中v是节点/顶点的数量,而e是的数量是{{1}}边缘)。

毫无疑问,有些技巧可以改善预期的性能,具体取决于DAG的属性及其随时间的变化情况。这似乎是一个活跃的研究课题。例如,我想某些图表可能对集群节点有益。在集群中插入边缘只需要在集群子DAG内进行检查。但是,您需要一个适当的群集策略,支持在添加节点时以便宜的方式更新群集等。

答案 1 :(得分:0)

不了解您的建议,但建议您添加索引。 每行索引必须存储对metaparent-metachild

metaparent - 链接中的父级:parent,parent-of-parent,...

metachid - 链接中的孩子:孩子,孩子,...

因此对于图A-> B-> C存在以下索引: A-B,B-C,A-C 在B-> C之间添加显式边缘导致断言,因为这样的条目已经存在。因此算法的复杂性从n ^ 2减少到ln(n)