【问题标题】:Finding the list of common children (descendants) for any two nodes in a cyclic graph查找循环图中任意两个节点的共同子节点(后代)列表
【发布时间】:2014-08-22 14:02:54
【问题描述】:

我有一个循环有向图,我想知道是否有任何算法(最好是最佳算法)来列出任意两个节点之间的共同后代?与最低共同祖先 (LCA) 所做的几乎相反。

【问题讨论】:

  • 在循环图中,节点可以是自身的后代。
  • 循环图中没有真正的后代。您正在寻找可从两个源顶点到达的一组顶点?
  • 您的意思是“常见相邻节点列表”吗?
  • 只需在两个节点上进行 DFS 并选择各自节点集的交集。
  • 我认为没有比使用 DFS 枚举 A 和 B 中所有可达节点并计算交集更好的解决方案了。您可以引入一些优化:如果您正在寻找 A 可到达的节点并偶然发现 B,您可以停止寻找并列出从 B 可到达的所有内容。

标签: algorithm graph-theory cyclic-graph


【解决方案1】:

正如 user1990169 所建议的,您可以使用 DFS 计算从每个起始顶点可到达的顶点集,然后返回交集。

如果您打算在同一个图上重复执行此操作,那么首先计算 strong components 并将其收缩为表示一组顶点的超顶点可能是值得的。作为副作用,您可以获得超顶点的拓扑顺序。这允许数据并行算法同时计算多个起始顶点的可达性。将所有顶点标签初始化为{}。对于每个起始顶点v,将标签设置为{v}。现在,按照拓扑顺序扫描所有顶点w,通过将x 的标签和w 的标签的并集来更新w 的外邻x 的标签。使用位集来紧凑、高效地表示集。缺点是我们不能像使用单一可达性计算那样进行修剪。

【讨论】:

  • 您不能将不在交叉点的顶点视为已访问。想象一下这张图 A -> D 和 B -> C -> D(A 和 B 是你的来源)。 D 可以从 B 到达,但只能通过 C,必须先遍历。
  • 但是,如果发现一个来源可以从另一个来源到达,您可以避免计算交集。
  • @biziclop 如果您有超过 2 个输入(OP 在评论中暗示了这一点),那么您可能仍然会在最后找到交集,但它可以节省在其中一个上运行搜索算法节点,因为它们具有相同的可达节点。
  • @Andrew_CS 不一样,但一个会包含另一个。
【解决方案2】:

我建议使用 DFS (depth first search)。

For each input node
    Create a collection to store reachable nodes
    Perform a DFS to find reachable nodes
        When a node is reached
            If it's already stored stop searching that path // Prevent cycles
            Else store it and continue

Find the intersection between all collections of nodes

注意:如果需要,您可以轻松地使用 BFS (breadth first search) 来代替相同的逻辑。


当您实现这一点时,请记住,您可以寻找一些特殊情况来进一步优化您的搜索,例如:

  • 如果输入节点没有任何顶点,则没有公共节点
  • 如果一个输入节点 (A) 到达另一个输入节点 (B),则 A 可以到达 B 所能到达的所有节点。
    这意味着算法不必在 B 上运行。

【讨论】:

    【解决方案3】:

    为什么不直接反转边缘的方向并使用 LCA?

    【讨论】:

    • 您知道这会起作用吗,并且只是将您的答案作为问题陈述?那你应该让你的答案更权威。或者您不确定,只是从 OP 的问题出发?那么这应该是评论,而不是答案。
    猜你喜欢
    • 2013-07-26
    • 1970-01-01
    • 2010-11-10
    • 2018-01-27
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 2017-12-25
    • 2011-09-01
    相关资源
    最近更新 更多