DAG中多个节点的最少共同祖先

时间:2012-07-12 10:06:22

标签: algorithm graph-algorithm directed-acyclic-graphs least-common-ancestor

如何在有向无环图中找到多个节点的最不常见的祖先?

我发现了很多关于这个主题的论文,但他们似乎都在DAG中找到两个节点的LCA。

多个节点有很好的算法吗?

2 个答案:

答案 0 :(得分:2)

也许您可以采用DAG方式修改用于树的算法。

您可能知道,有一种算法可以在树中找到LCA,其中 O(nlgn)的预处理和每个查询的 O(1)处理,因此找到 k 节点的LCA需要 O(k)。有关此算法的更多详细信息,请参见here

答案 1 :(得分:0)

正如@ DennisMeng,@ vzn和@ user824425在评论中已经指出的那样,在某些情况下(!),可以通过(二进制)LCA运算符的逐对递归应用来计算两个以上节点的LCA < / strong>,例如:

lca(A, B, C, D) = lca(A, lca(B, lca(C, D)))

在函数式编程中,这基本上等效于 reduce (或fold)操作。

但是,这仅适用于Multitrees(或可选的无钻石posets)DAG。对于不具有多树/无钻石姿势属性的常规DAG,不幸的是,此方法不起作用

请考虑以下DAG,它表示具有多个继承特征的类层次结构(所有边均从底部指向顶部; X表示两个有向边的交叉):

        Any
       /   \
  Boolean Value 
      |  X  |  \
    False True Unknown

值得注意的是,TrueFalse节点都有两个直接祖先,BooleanValue。这里的第一个问题是,这需要一个LCA运算符,该运算符可以返回多个节点,例如JGraphTgetLCASet。现在,假设我们要计算{FalseTrueUnknown}的LCA:仅通过查看图表,很明显Value是一个这三个节点的直接祖先。直接成对约简不再适用,因为二进制getLCASet运算符可以返回多个节点,但是可以想象,可以使用类似堆栈的方法,其中计算的祖先被推回到节点列表中。但是,这不会产生正确的结果,例如:

  True, False, Unknown
     \   /
     (LCA)
     /   \
Boolean, Value, Unknown
     \   /
     (LCA)
       |
      Any, Unknown
        \   /
        (LCA)
          |
         Any