从MaxFlow中提升MinCut

时间:2009-11-05 06:34:19

标签: c++ boost graph

我需要获得图表的st-MinCut。我最近开始使用C ++ Boost库,它们似乎没有st-MinCut功能,但是它有MaxFlow实现,我可以(理论上)利用MaxFlow / MinCut二元性。

我已经得到了“push relabel max flow”功能正常工作,但是我无法弄清楚如何从剩余容量大于0的边缘来源运行DFS,以获得节点来源方。

提前致谢。

2 个答案:

答案 0 :(得分:0)

您可以使用filtered_graph创建一个(虚拟)图表,其边缘的剩余容量非零(或任何其他条件)

答案 1 :(得分:0)

我是按照以下方式完成的(LEDA图形库具有为您完成的功能)。我迭代图上的所有边并收集所有饱和或零流的边。现在,这些边缘的子集必须是最小切割。

然后我用gsl_combination.h生成了这个集合的子集。检查每个子集的切割值是否等于最大流量。如果否,则生成下一个子集,如果是,则检查从图中删除这些边是否会将图分成两部分。现在您的问题是如何检查从图中删除某些边缘是否将图形分成两部分,使得一部分具有源和其他汇聚节点。

这很简单。从图中删除那些作为可能的割集给出的边。创建堆栈ss并将源节点推送到它。现在创建一个while循环,当ss为空时终止循环。内部循环pop来自ss的节点,并从ss获取所有外出边缘;推送到这些边缘的ss target顶点。如果在迭代期间,您发现一个等于sink节点的节点,这意味着源和宿两者之间都有一条路径。因此它不是削减。我正在放一段代码。请注意,我没有从图中删除边,我只是将它们的流设置为0.我从曲线图中删除了从边缘移除零流的所有边。

template<typename Graph>
vector<typename Graph::edge_descriptor> getMinCutWhenFlowIsGiven(
    Graph& flowG, typename Graph::vertex_descriptor src
    , typename Graph::vertex_descriptor tgt
    , unsigned flow)
{
  /* Find saturated edges */
  vector<typename Graph::edge_descriptor> possibleCutEdges;
  unsigned totalCutWeight = 0;

  /* Find all saturated or zero-flow edges. */
  for(auto e = edges(flowG); e.first != e.second; e.first++)
  {
    typename Graph::edge_descriptor ee = *e.first;
    if(flowG[ee].flow == 0 || flowG[ee].capacity - flowG[ee].flow == 0)
    {
      possibleCutEdges.push_back(ee);
      totalCutWeight += flowG[ee].flow;
      cerr << flowG[ee].flow << ",";
    }
  }
  cerr << endl;
  cerr << "[INFO] Total " << possibleCutEdges.size() << " edges." 
    << " with capacity : " << totalCutWeight 
    << " in flow-network after flow-computation." << endl;


#if  SAVE_GRAPH
  /* Save this graph. */
  write_graph(flowG, "dots/overlap.ml");
#endif     /* -----  SAVE_GRAPH  ----- */


  /*-----------------------------------------------------------------------------
   * Good, now we have a set of vertices. Generate all possible subsets of set
   * and see if any of them satisfy our need.
   *-----------------------------------------------------------------------------*/
  size_t n = possibleCutEdges.size();

  vector<typename Graph::edge_descriptor> cut;

  gsl_combination *c;
  for (size_t i = 0; i < n; i++)
  {
    c = gsl_combination_calloc (n, i);
    do
    {
      /* Check if this combination satify the max-flow condition */
      unsigned edgesFlow = 0;
      vector<typename Graph::edge_descriptor> potentialCut;
      for(size_t ii = 0; ii < c->k; ii++)
      {
        size_t elem = gsl_combination_get(c, ii);
        edgesFlow += flowG[possibleCutEdges[elem]].flow;
        potentialCut.push_back(possibleCutEdges[elem]);
      }
      if(edgesFlow == flow)
      {
        if(isCut(potentialCut, flowG, src, tgt))
          return potentialCut;  // got it!
      }
    }
    while (gsl_combination_next (c) == GSL_SUCCESS);
    gsl_combination_free (c);
  }
  return cut;
}