COIN-OR::LEMON - Graph Library

Ticket #66: 5ecf45167d4e.patch

File 5ecf45167d4e.patch, 6.2 KB (added by Alpar Juttner, 11 years ago)
  • lemon/gomory_hu_tree.h

    # HG changeset patch
    # User Alpar Juttner <alpar@cs.elte.hu>
    # Date 1235495094 0
    # Node ID 5ecf45167d4efec2816dab32f43ad0093bb2e3cf
    # Parent  926295286bdb51ee3cb4c9937296a0d5a728fdfa
    Cut iterator for GomoryHuTree + bug fixes
    
    diff --git a/lemon/gomory_hu_tree.h b/lemon/gomory_hu_tree.h
    a b  
    228228     
    229229      while (sn != tn) {
    230230        if ((*_order)[sn] < (*_order)[tn]) {
    231           if ((*_weight)[tn] < value) value = (*_weight)[tn];
     231          if ((*_weight)[tn] <= value) value = (*_weight)[tn];
    232232          tn = (*_pred)[tn];
    233233        } else {
    234           if ((*_weight)[sn] < value) value = (*_weight)[sn];
     234          if ((*_weight)[sn] <= value) value = (*_weight)[sn];
    235235          sn = (*_pred)[sn];
    236236        }
    237237      }
     
    249249    template <typename CutMap>
    250250    Value minCutMap(const Node& s, const Node& t, CutMap& cutMap) const {
    251251      Node sn = s, tn = t;
    252 
     252      bool s_root=false;
    253253      Node rn = INVALID;
    254254      Value value = std::numeric_limits<Value>::max();
    255255     
    256256      while (sn != tn) {
    257257        if ((*_order)[sn] < (*_order)[tn]) {
    258           if ((*_weight)[tn] < value) {
     258          if ((*_weight)[tn] <= value) {
    259259            rn = tn;
     260            s_root = false;
    260261            value = (*_weight)[tn];
    261262          }
    262263          tn = (*_pred)[tn];
    263264        } else {
    264           if ((*_weight)[sn] < value) {
     265          if ((*_weight)[sn] <= value) {
    265266            rn = sn;
     267            s_root = true;
    266268            value = (*_weight)[sn];
    267269          }
    268270          sn = (*_pred)[sn];
     
    271273
    272274      typename Graph::template NodeMap<bool> reached(_graph, false);
    273275      reached.set(_root, true);
    274       cutMap.set(_root, false);
     276      cutMap.set(_root, !s_root);
    275277      reached.set(rn, true);
    276       cutMap.set(rn, true);
     278      cutMap.set(rn, s_root);
    277279
     280      std::vector<Node> st;
    278281      for (NodeIt n(_graph); n != INVALID; ++n) {
    279         std::vector<Node> st;
    280         Node nn = n;
     282        st.clear();
     283        Node nn = n;
    281284        while (!reached[nn]) {
    282285          st.push_back(nn);
    283286          nn = (*_pred)[nn];
     
    291294      return value;
    292295    }
    293296
     297    friend class MinCutNodeIt;
     298
     299    class MinCutNodeIt
     300    {
     301      bool _side;
     302      typename Graph::NodeIt _node_it;
     303      typename Graph::template NodeMap<bool> _cut;
     304    public:
     305      MinCutNodeIt(GomoryHuTree const &gomory,
     306                   const Node& s, const Node& t, bool side=true)
     307        : _side(side), _cut(gomory._graph)
     308      {
     309        gomory.minCutMap(s,t,_cut);
     310        for(_node_it=typename Graph::NodeIt(gomory._graph);
     311            _node_it!=INVALID && _cut[_node_it]!=_side;
     312            ++_node_it) {}
     313      }
     314      operator typename Graph::Node() const
     315      {
     316        return _node_it;
     317      }
     318      bool operator==(Invalid) { return _node_it==INVALID; }
     319      bool operator!=(Invalid) { return _node_it!=INVALID; }
     320      ///Next node
     321      MinCutNodeIt &operator++()
     322      {
     323        for(++_node_it;_node_it!=INVALID&&_cut[_node_it]!=_side;++_node_it) {}
     324        return *this;
     325      }
     326      ///Postfix incrementation
     327
     328      ///\warning This incrementation
     329      ///returns a \c Node, not a \ref MinCutNodeIt, as one may
     330      ///expect.
     331      typename Graph::Node operator++(int)
     332      {
     333        typename Graph::Node n=*this;
     334        ++(*this);
     335        return n;
     336      }
     337    };
     338   
     339    friend class MinCutArcIt;
     340   
     341    class MinCutArcIt
     342    {
     343      bool _side;
     344      const Graph &_graph;
     345      typename Graph::NodeIt _node_it;
     346      typename Graph::OutArcIt _arc_it;
     347      typename Graph::template NodeMap<bool> _cut;
     348      void step()
     349      {
     350        ++_arc_it;
     351        while(_node_it!=INVALID && _arc_it==INVALID)
     352          {
     353            for(++_node_it;_node_it!=INVALID&&!_cut[_node_it];++_node_it) {}
     354            if(_node_it!=INVALID)
     355              _arc_it=typename Graph::OutArcIt(_graph,_node_it);
     356          }
     357      }
     358     
     359    public:
     360      MinCutArcIt(GomoryHuTree const &gomory,
     361                  const Node& s, const Node& t, bool side=true)
     362        : _graph(gomory._graph), _cut(_graph)
     363      {
     364        gomory.minCutMap(s,t,_cut);
     365        if(!side)
     366          for(typename Graph::NodeIt n(_graph);n!=INVALID;++n)
     367            _cut[n]=!_cut[n];
     368
     369        for(_node_it=typename Graph::NodeIt(_graph);
     370            _node_it!=INVALID && !_cut[_node_it];
     371            ++_node_it) {}
     372        _arc_it = _node_it!=INVALID ?
     373          typename Graph::OutArcIt(_graph,_node_it) : INVALID;
     374        while(_node_it!=INVALID && _arc_it == INVALID)
     375          {
     376            for(++_node_it; _node_it!=INVALID&&!_cut[_node_it]; ++_node_it) {}
     377            if(_node_it!=INVALID)
     378              _arc_it= typename Graph::OutArcIt(_graph,_node_it);
     379          }
     380        while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
     381      }
     382      operator typename Graph::Arc() const
     383      {
     384        return _arc_it;
     385      }
     386      operator typename Graph::Edge() const
     387      {
     388        return _arc_it;
     389      }
     390      bool operator==(Invalid) { return _node_it==INVALID; }
     391      bool operator!=(Invalid) { return _node_it!=INVALID; }
     392      ///Next node
     393      MinCutArcIt &operator++()
     394      {
     395        step();
     396        while(_arc_it!=INVALID && _cut[_graph.target(_arc_it)]) step();
     397        return *this;
     398      }
     399      ///Postfix incrementation
     400     
     401      ///\warning This incrementation
     402      ///returns a \c Arc, not a \ref MinCutArcIt, as one may
     403      ///expect.
     404      typename Graph::Arc operator++(int)
     405      {
     406        typename Graph::Arc a=*this;
     407        ++(*this);
     408        return a;
     409      }
     410    };
     411
    294412  };
    295413
    296414}
  • test/gomory_hu_test.cc

    diff --git a/test/gomory_hu_test.cc b/test/gomory_hu_test.cc
    a b  
    7777      check(pf.flowValue() == ght.minCutValue(u, v), "Wrong cut 1");
    7878      check(cm[u] != cm[v], "Wrong cut 3");
    7979      check(pf.flowValue() == cutValue(graph, cm, capacity), "Wrong cut 2");
     80
     81      int sum=0;
     82      for(GomoryHuTree<Graph>::MinCutArcIt a(ght, u, v);a!=INVALID;++a)
     83        sum+=capacity[a];
     84      check(sum == ght.minCutValue(u, v), "Problem with MinCutArcIt");
     85
     86      sum=0;
     87      for(GomoryHuTree<Graph>::MinCutNodeIt n(ght, u, v,true);n!=INVALID;++n)
     88        sum++;
     89      for(GomoryHuTree<Graph>::MinCutNodeIt n(ght, u, v,false);n!=INVALID;++n)
     90        sum++;
     91      check(sum == countNodes(graph), "Problem with MinCutNodeIt");
    8092     
    8193    }
    8294  }