如何在较大的强连接组件中找到强连接组件?

时间:2017-02-27 04:40:44

标签: c++ graph llvm

我有一个程序需要在有向图中检测循环(以及属于该循环的成员的节点)。为此,我使用LLVM的强连接组件算法。它非常易于使用,它的功能非常接近:

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

这正确识别简单的SCC,如下所示:

Strongly-connected component: node A goes to node B, node B goes to node C, node C goes to node B and D. Nodes B and C are part of a strongly-connected compoenent.

这很棒,但我很想知道每个较大的强连接组件中何时有强连接组件。例如,这被标识为单个SCC:

Same graph as before, except that there is an edge from D to A.

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

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

1 个答案:

答案 0 :(得分:2)

所以我试图制作一个很好的回复/你可以使用更多可用功能做的事情,但是它正在离线工作并且我的计算机崩溃了:(。

我已经重新创建了我想要说的内核,它只解决了您的直接问题/示例,在伪代码中使用不存在的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;
}

这当然没有效率或漂亮,但应足以让你对这个问题有所了解。