【问题标题】:How can I find strongly-connected components within larger strongly-connected components?如何在较大的强连接组件中找到强连接组件?
【发布时间】:2017-02-27 04:40:44
【问题描述】:

我有一个程序需要在有向图中检测循环(以及作为该循环成员的节点)。为此,我使用 LLVM 的强连接组件算法。它非常易于使用,并且几乎可以完成应有的工作:

vector<vector<PreAstBasicBlock*>> stronglyConnectedComponents;
for (auto iter = scc_begin(&function); iter != scc_end(&function); ++iter)
{
    if (iter.hasLoop())
    {
        stronglyConnectedComponents.push_back(*iter);
    }
}

这可以正确识别简单的 SCC,比如这个简单的:

这很好,但我很想知道我什么时候在每个更大的强连接组件中都有强连接组件。例如,这被识别为单个 SCC:

这绝对正确,因为该图中的每个节点都可以从任何其他节点开始访问。但是,B⇄C 具有独立于 D→A 后沿的附加属性。它本身就是一个 SCC,它有一个入口节点和一个出口节点:我可以用一个单一节点替换它,而且我不会有边缘插入或伸出它的概念中间。

如何在强连接组件中找到这些较小的强连接组件?

【问题讨论】:

  • @user2899162,我不确定你的意思。两个图中都没有 C→A 边,所以在我看来,如果将其识别为循环就会出现问题。为了澄清,在每个屏幕截图中,绿色框是被识别的强连接组件,它作为一组节点返回。
  • @user2899162,很像 LLVM CFG,我的图表总是有一个“自然条目”(在这些示例中为 A),并且不能循环返回该自然条目(更一般地说,会有始终是从外部戳到自然入口的边缘)。你可以有 A→B→C→D→B,但它会(应该?)找到 B→C→D→B。

标签: c++ graph llvm


【解决方案1】:

所以我试图做出一个很好的回应/你可以用更多可用的功能做的事情,但是我离线处理它并且我的电脑崩溃了:(。

我已经重新创建了我想说的核心,它只解决了你的直接问题/示例,使用不存在的 GetConnectedComponents(...) 辅助函数的伪代码,你可以从上下文中理解其理想化行为:

bool HasConnectedSubgraph(Graph& entire_graph) {
  for (const auto& connected_subgraph : GetConnectedComponents(entire_graph)
    for (const auto& connected_node : connected_subgraph) {
      local_copy = connected_subgraph;
      local_copy.erase(std::remove_if(local_copy.begin(), local_copy.end(), 
          [&](const Node& n) {return n == connected_node}) , local_copy.end());
      if (!GetConnectedComponents(local_copy).empty()) {
        return true;
      }
    }
  }
  return false;
}

这当然不是高效或漂亮,但应该足以让您对这个问题产生想法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-28
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    相关资源
    最近更新 更多