COIN-OR::LEMON - Graph Library

Changeset 2505:1bb471764ab8 in lemon-0.x for lemon/max_matching.h


Ignore:
Timestamp:
10/30/07 21:21:10 (17 years ago)
Author:
Balazs Dezso
Branch:
default
Phase:
public
Convert:
svn:c9d7d8f5-90d6-0310-b91f-818b3a526b0e/lemon/trunk@3351
Message:

Redesign interface of MaxMatching? and UnionFindEnum?
New class ExtendFindEnum?

Faster MaxMatching?

File:
1 edited

Legend:

Unmodified
Added
Removed
  • lemon/max_matching.h

    r2391 r2505  
    3131namespace lemon {
    3232
    33   /// \ingroup matching
    34 
    35   ///Edmonds' alternating forest maximum matching algorithm.
    36 
     33  ///\ingroup matching
     34
     35  ///\brief Edmonds' alternating forest maximum matching algorithm.
     36  ///
    3737  ///This class provides Edmonds' alternating forest matching
    3838  ///algorithm. The starting matching (if any) can be passed to the
    39   ///algorithm using read-in functions \ref readNMapNode, \ref
    40   ///readNMapEdge or \ref readEMapBool depending on the container. The
    41   ///resulting maximum matching can be attained by write-out functions
    42   ///\ref writeNMapNode, \ref writeNMapEdge or \ref writeEMapBool
    43   ///depending on the preferred container.
     39  ///algorithm using some of init functions.
    4440  ///
    4541  ///The dual side of a matching is a map of the nodes to
    46   ///MaxMatching::pos_enum, having values D, A and C showing the
    47   ///Gallai-Edmonds decomposition of the graph. The nodes in D induce
    48   ///a graph with factor-critical components, the nodes in A form the
    49   ///barrier, and the nodes in C induce a graph having a perfect
    50   ///matching. This decomposition can be attained by calling \ref
    51   ///writePos after running the algorithm.
     42  ///MaxMatching::DecompType, having values \c D, \c A and \c C
     43  ///showing the Gallai-Edmonds decomposition of the graph. The nodes
     44  ///in \c D induce a graph with factor-critical components, the nodes
     45  ///in \c A form the barrier, and the nodes in \c C induce a graph
     46  ///having a perfect matching. This decomposition can be attained by
     47  ///calling \c decomposition() after running the algorithm.
    5248  ///
    5349  ///\param Graph The undirected graph type the algorithm runs on.
     
    6864    typedef typename Graph::template NodeMap<int> UFECrossRef;
    6965    typedef UnionFindEnum<UFECrossRef> UFE;
     66    typedef std::vector<Node> NV;
     67
     68    typedef typename Graph::template NodeMap<int> EFECrossRef;
     69    typedef ExtendFindEnum<EFECrossRef> EFE;
    7070
    7171  public:
    7272   
    73     ///Indicates the Gallai-Edmonds decomposition of the graph.
    74 
     73    ///\brief Indicates the Gallai-Edmonds decomposition of the graph.
     74    ///
    7575    ///Indicates the Gallai-Edmonds decomposition of the graph, which
    7676    ///shows an upper bound on the size of a maximum matching. The
    77     ///nodes with pos_enum \c D induce a graph with factor-critical
     77    ///nodes with DecompType \c D induce a graph with factor-critical
    7878    ///components, the nodes in \c A form the canonical barrier, and the
    7979    ///nodes in \c C induce a graph having a perfect matching.
    80     enum pos_enum {
     80    enum DecompType {
    8181      D=0,
    8282      A=1,
     
    8989    const Graph& g;
    9090    typename Graph::template NodeMap<Node> _mate;
    91     typename Graph::template NodeMap<pos_enum> position;
     91    typename Graph::template NodeMap<DecompType> position;
    9292     
    9393  public:
    9494   
    95     MaxMatching(const Graph& _g) : g(_g), _mate(_g,INVALID), position(_g) {}
    96 
    97     ///Runs Edmonds' algorithm.
    98 
    99     ///Runs Edmonds' algorithm for sparse graphs (number of edges <
    100     ///2*number of nodes), and a heuristical Edmonds' algorithm with a
    101     ///heuristic of postponing shrinks for dense graphs.
    102     void run() {
    103       if ( countUEdges(g) < HEUR_density*countNodes(g) ) {
    104         greedyMatching();
    105         runEdmonds(0);
    106       } else runEdmonds(1);
    107     }
    108 
    109 
    110     ///Runs Edmonds' algorithm.
    111    
    112     ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs
    113     ///Edmonds' algorithm with a heuristic of postponing shrinks,
    114     ///giving a faster algorithm for dense graphs. 
    115     void runEdmonds( int heur = 1 ) {
    116      
    117       //each vertex is put to C
    118       for(NodeIt v(g); v!=INVALID; ++v)
    119         position.set(v,C);     
    120      
    121       typename Graph::template NodeMap<Node> ear(g,INVALID);
    122       //undefined for the base nodes of the blossoms (i.e. for the
    123       //representative elements of UFE blossom) and for the nodes in C
    124      
    125       UFECrossRef blossom_base(g);
    126       UFE blossom(blossom_base);
    127 
    128       UFECrossRef tree_base(g);
    129       UFE tree(tree_base);
    130 
    131       //If these UFE's would be members of the class then also
    132       //blossom_base and tree_base should be a member.
    133      
    134       //We build only one tree and the other vertices uncovered by the
    135       //matching belong to C. (They can be considered as singleton
    136       //trees.) If this tree can be augmented or no more
    137       //grow/augmentation/shrink is possible then we return to this
    138       //"for" cycle.
    139       for(NodeIt v(g); v!=INVALID; ++v) {
    140         if ( position[v]==C && _mate[v]==INVALID ) {
    141           blossom.insert(v);
    142           tree.insert(v);
    143           position.set(v,D);
    144           if ( heur == 1 ) lateShrink( v, ear, blossom, tree );
    145           else normShrink( v, ear, blossom, tree );
    146         }
    147       }
    148     }
    149 
    150 
    151     ///Finds a greedy matching starting from the actual matching.
    152    
    153     ///Starting form the actual matching stored, it finds a maximal
    154     ///greedy matching.
    155     void greedyMatching() {
     95    MaxMatching(const Graph& _g)
     96      : g(_g), _mate(_g), position(_g) {}
     97
     98    ///\brief Sets the actual matching to the empty matching.
     99    ///
     100    ///Sets the actual matching to the empty matching. 
     101    ///
     102    void init() {
     103      for(NodeIt v(g); v!=INVALID; ++v) {
     104        _mate.set(v,INVALID);     
     105        position.set(v,C);
     106      }
     107    }
     108
     109    ///\brief Finds a greedy matching for initial matching.
     110    ///
     111    ///For initial matchig it finds a maximal greedy matching.
     112    void greedyInit() {
     113      for(NodeIt v(g); v!=INVALID; ++v) {
     114        _mate.set(v,INVALID);     
     115        position.set(v,C);
     116      }
    156117      for(NodeIt v(g); v!=INVALID; ++v)
    157118        if ( _mate[v]==INVALID ) {
     
    167128    }
    168129
    169     ///Returns the size of the actual matching stored.
    170 
     130    ///\brief Initialize the matching from each nodes' mate.
     131    ///
     132    ///Initialize the matching from a \c Node valued \c Node map. This
     133    ///map must be \e symmetric, i.e. if \c map[u]==v then \c
     134    ///map[v]==u must hold, and \c uv will be an edge of the initial
     135    ///matching.
     136    template <typename MateMap>
     137    void mateMapInit(MateMap& map) {
     138      for(NodeIt v(g); v!=INVALID; ++v) {
     139        _mate.set(v,map[v]);
     140        position.set(v,C);
     141      }
     142    }
     143
     144    ///\brief Initialize the matching from a node map with the
     145    ///incident matching edges.
     146    ///
     147    ///Initialize the matching from an \c UEdge valued \c Node map. \c
     148    ///map[v] must be an \c UEdge incident to \c v. This map must have
     149    ///the property that if \c g.oppositeNode(u,map[u])==v then \c \c
     150    ///g.oppositeNode(v,map[v])==u holds, and now some edge joining \c
     151    ///u to \c v will be an edge of the matching.
     152    template<typename MatchingMap>
     153    void matchingMapInit(MatchingMap& map) {
     154      for(NodeIt v(g); v!=INVALID; ++v) {
     155        position.set(v,C);
     156        UEdge e=map[v];
     157        if ( e!=INVALID )
     158          _mate.set(v,g.oppositeNode(v,e));
     159        else
     160          _mate.set(v,INVALID);
     161      }
     162    }
     163
     164    ///\brief Initialize the matching from the map containing the
     165    ///undirected matching edges.
     166    ///
     167    ///Initialize the matching from a \c bool valued \c UEdge map. This
     168    ///map must have the property that there are no two incident edges
     169    ///\c e, \c f with \c map[e]==map[f]==true. The edges \c e with \c
     170    ///map[e]==true form the matching.
     171    template <typename MatchingMap>
     172    void matchingInit(MatchingMap& map) {
     173      for(NodeIt v(g); v!=INVALID; ++v) {
     174        _mate.set(v,INVALID);     
     175        position.set(v,C);
     176      }
     177      for(UEdgeIt e(g); e!=INVALID; ++e) {
     178        if ( map[e] ) {
     179          Node u=g.source(e);     
     180          Node v=g.target(e);
     181          _mate.set(u,v);
     182          _mate.set(v,u);
     183        }
     184      }
     185    }
     186
     187
     188    ///\brief Runs Edmonds' algorithm.
     189    ///
     190    ///Runs Edmonds' algorithm for sparse graphs (number of edges <
     191    ///2*number of nodes), and a heuristical Edmonds' algorithm with a
     192    ///heuristic of postponing shrinks for dense graphs.
     193    void run() {
     194      if (countUEdges(g) < HEUR_density * countNodes(g)) {
     195        greedyInit();
     196        startSparse();
     197      } else {
     198        init();
     199        startDense();
     200      }
     201    }
     202
     203
     204    ///\brief Starts Edmonds' algorithm.
     205    ///
     206    ///If runs the original Edmonds' algorithm. 
     207    void startSparse() {
     208           
     209      typename Graph::template NodeMap<Node> ear(g,INVALID);
     210      //undefined for the base nodes of the blossoms (i.e. for the
     211      //representative elements of UFE blossom) and for the nodes in C
     212     
     213      UFECrossRef blossom_base(g);
     214      UFE blossom(blossom_base);
     215      NV rep(countNodes(g));
     216
     217      EFECrossRef tree_base(g);
     218      EFE tree(tree_base);
     219
     220      //If these UFE's would be members of the class then also
     221      //blossom_base and tree_base should be a member.
     222     
     223      //We build only one tree and the other vertices uncovered by the
     224      //matching belong to C. (They can be considered as singleton
     225      //trees.) If this tree can be augmented or no more
     226      //grow/augmentation/shrink is possible then we return to this
     227      //"for" cycle.
     228      for(NodeIt v(g); v!=INVALID; ++v) {
     229        if (position[v]==C && _mate[v]==INVALID) {
     230          rep[blossom.insert(v)] = v;
     231          tree.insert(v);
     232          position.set(v,D);
     233          normShrink(v, ear, blossom, rep, tree);
     234        }
     235      }
     236    }
     237
     238    ///\brief Starts Edmonds' algorithm.
     239    ///
     240    ///It runs Edmonds' algorithm with a heuristic of postponing
     241    ///shrinks, giving a faster algorithm for dense graphs.
     242    void startDense() {
     243           
     244      typename Graph::template NodeMap<Node> ear(g,INVALID);
     245      //undefined for the base nodes of the blossoms (i.e. for the
     246      //representative elements of UFE blossom) and for the nodes in C
     247     
     248      UFECrossRef blossom_base(g);
     249      UFE blossom(blossom_base);
     250      NV rep(countNodes(g));
     251
     252      EFECrossRef tree_base(g);
     253      EFE tree(tree_base);
     254
     255      //If these UFE's would be members of the class then also
     256      //blossom_base and tree_base should be a member.
     257     
     258      //We build only one tree and the other vertices uncovered by the
     259      //matching belong to C. (They can be considered as singleton
     260      //trees.) If this tree can be augmented or no more
     261      //grow/augmentation/shrink is possible then we return to this
     262      //"for" cycle.
     263      for(NodeIt v(g); v!=INVALID; ++v) {
     264        if ( position[v]==C && _mate[v]==INVALID ) {
     265          rep[blossom.insert(v)] = v;
     266          tree.insert(v);
     267          position.set(v,D);
     268          lateShrink(v, ear, blossom, rep, tree);
     269        }
     270      }
     271    }
     272
     273
     274
     275    ///\brief Returns the size of the actual matching stored.
     276    ///
    171277    ///Returns the size of the actual matching stored. After \ref
    172278    ///run() it returns the size of a maximum matching in the graph.
     
    182288
    183289
    184     ///Resets the actual matching to the empty matching.
    185 
    186     ///Resets the actual matching to the empty matching. 
    187     ///
    188     void resetMatching() {
    189       for(NodeIt v(g); v!=INVALID; ++v)
    190         _mate.set(v,INVALID);     
    191     }
    192 
    193     ///Returns the mate of a node in the actual matching.
    194 
     290    ///\brief Returns the mate of a node in the actual matching.
     291    ///
    195292    ///Returns the mate of a \c node in the actual matching.
    196293    ///Returns INVALID if the \c node is not covered by the actual matching.
    197     Node mate(Node& node) const {
     294    Node mate(const Node& node) const {
    198295      return _mate[node];
    199296    }
    200297
    201     ///Reads a matching from a \c Node valued \c Node map.
    202 
    203     ///Reads a matching from a \c Node valued \c Node map. This map
    204     ///must be \e symmetric, i.e. if \c map[u]==v then \c map[v]==u
    205     ///must hold, and \c uv will be an edge of the matching.
    206     template<typename NMapN>
    207     void readNMapNode(NMapN& map) {
    208       for(NodeIt v(g); v!=INVALID; ++v) {
    209         _mate.set(v,map[v]);   
    210       }
     298    ///\brief Returns the matching edge incident to the given node.
     299    ///
     300    ///Returns the matching edge of a \c node in the actual matching.
     301    ///Returns INVALID if the \c node is not covered by the actual matching.
     302    UEdge matchingEdge(const Node& node) const {
     303      if (_mate[node] == INVALID) return INVALID;
     304      Node n = node < _mate[node] ? node : _mate[node];
     305      for (IncEdgeIt e(g, n); e != INVALID; ++e) {
     306        if (g.oppositeNode(n, e) == _mate[n]) {
     307          return e;
     308        }
     309      }
     310      return INVALID;
    211311    }
    212    
    213     ///Writes the stored matching to a \c Node valued \c Node map.
    214 
     312
     313    /// \brief Returns the class of the node in the Edmonds-Gallai
     314    /// decomposition.
     315    ///
     316    /// Returns the class of the node in the Edmonds-Gallai
     317    /// decomposition.
     318    DecompType decomposition(const Node& n) {
     319      return position[n] == A;
     320    }
     321
     322    /// \brief Returns true when the node is in the barrier.
     323    ///
     324    /// Returns true when the node is in the barrier.
     325    bool barrier(const Node& n) {
     326      return position[n] == A;
     327    }
     328   
     329    ///\brief Gives back the matching in a \c Node of mates.
     330    ///
    215331    ///Writes the stored matching to a \c Node valued \c Node map. The
    216332    ///resulting map will be \e symmetric, i.e. if \c map[u]==v then \c
    217333    ///map[v]==u will hold, and now \c uv is an edge of the matching.
    218     template<typename NMapN>
    219     void writeNMapNode (NMapN& map) const {
     334    template <typename MateMap>
     335    void mateMap(MateMap& map) const {
    220336      for(NodeIt v(g); v!=INVALID; ++v) {
    221337        map.set(v,_mate[v]);   
    222338      }
    223339    }
    224 
    225     ///Reads a matching from an \c UEdge valued \c Node map.
    226 
    227     ///Reads a matching from an \c UEdge valued \c Node map. \c
    228     ///map[v] must be an \c UEdge incident to \c v. This map must
    229     ///have the property that if \c g.oppositeNode(u,map[u])==v then
    230     ///\c \c g.oppositeNode(v,map[v])==u holds, and now some edge
    231     ///joining \c u to \c v will be an edge of the matching.
    232     template<typename NMapE>
    233     void readNMapEdge(NMapE& map) {
    234       for(NodeIt v(g); v!=INVALID; ++v) {
    235         UEdge e=map[v];
    236         if ( e!=INVALID )
    237           _mate.set(v,g.oppositeNode(v,e));
    238       }
    239     }
    240    
    241     ///Writes the matching stored to an \c UEdge valued \c Node map.
    242 
     340   
     341    ///\brief Gives back the matching in an \c UEdge valued \c Node
     342    ///map.
     343    ///
    243344    ///Writes the stored matching to an \c UEdge valued \c Node
    244345    ///map. \c map[v] will be an \c UEdge incident to \c v. This
     
    246347    ///== v then \c map[u]==map[v] holds, and now this edge is an edge
    247348    ///of the matching.
    248     template<typename NMapE>
    249     void writeNMapEdge (NMapE& map)  const {
     349    template <typename MatchingMap>
     350    void matchingMap(MatchingMap& map)  const {
    250351      typename Graph::template NodeMap<bool> todo(g,true);
    251352      for(NodeIt v(g); v!=INVALID; ++v) {
    252         if ( todo[v] && _mate[v]!=INVALID ) {
     353        if (_mate[v]!=INVALID && v < _mate[v]) {
    253354          Node u=_mate[v];
    254355          for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
     
    266367
    267368
    268     ///Reads a matching from a \c bool valued \c Edge map.
    269    
    270     ///Reads a matching from a \c bool valued \c Edge map. This map
    271     ///must have the property that there are no two incident edges \c
    272     ///e, \c f with \c map[e]==map[f]==true. The edges \c e with \c
    273     ///map[e]==true form the matching.
    274     template<typename EMapB>
    275     void readEMapBool(EMapB& map) {
    276       for(UEdgeIt e(g); e!=INVALID; ++e) {
    277         if ( map[e] ) {
    278           Node u=g.source(e);     
    279           Node v=g.target(e);
    280           _mate.set(u,v);
    281           _mate.set(v,u);
    282         }
    283       }
    284     }
    285 
    286 
    287     ///Writes the matching stored to a \c bool valued \c Edge map.
    288 
     369    ///\brief Gives back the matching in a \c bool valued \c UEdge
     370    ///map.
     371    ///
    289372    ///Writes the matching stored to a \c bool valued \c Edge
    290373    ///map. This map will have the property that there are no two
    291374    ///incident edges \c e, \c f with \c map[e]==map[f]==true. The
    292375    ///edges \c e with \c map[e]==true form the matching.
    293     template<typename EMapB>
    294     void writeEMapBool (EMapB& map) const {
     376    template<typename MatchingMap>
     377    void matching(MatchingMap& map) const {
    295378      for(UEdgeIt e(g); e!=INVALID; ++e) map.set(e,false);
    296379
     
    312395
    313396
    314     ///Writes the canonical decomposition of the graph after running
     397    ///\brief Returns the canonical decomposition of the graph after running
    315398    ///the algorithm.
    316 
     399    ///
    317400    ///After calling any run methods of the class, it writes the
    318401    ///Gallai-Edmonds canonical decomposition of the graph. \c map
    319     ///must be a node map of \ref pos_enum 's.
    320     template<typename NMapEnum>
    321     void writePos (NMapEnum& map) const {
    322       for(NodeIt v(g); v!=INVALID; ++v)  map.set(v,position[v]);
     402    ///must be a node map of \ref DecompType 's.
     403    template <typename DecompositionMap>
     404    void decomposition(DecompositionMap& map) const {
     405      for(NodeIt v(g); v!=INVALID; ++v) map.set(v,position[v]);
     406    }
     407
     408    ///\brief Returns a barrier on the nodes.
     409    ///
     410    ///After calling any run methods of the class, it writes a
     411    ///canonical barrier on the nodes. The odd component number of the
     412    ///remaining graph minus the barrier size is a lower bound for the
     413    ///uncovered nodes in the graph. The \c map must be a node map of
     414    ///bools.
     415    template <typename BarrierMap>
     416    void barrier(BarrierMap& barrier) {
     417      for(NodeIt v(g); v!=INVALID; ++v) barrier.set(v,position[v] == A);   
    323418    }
    324419
     
    327422 
    328423    void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear, 
    329                     UFE& blossom, UFE& tree);
     424                    UFE& blossom, NV& rep, EFE& tree) {
     425      //We have one tree which we grow, and also shrink but only if it
     426      //cannot be postponed. If we augment then we return to the "for"
     427      //cycle of runEdmonds().
     428
     429      std::queue<Node> Q;   //queue of the totally unscanned nodes
     430      Q.push(v); 
     431      std::queue<Node> R;   
     432      //queue of the nodes which must be scanned for a possible shrink
     433     
     434      while ( !Q.empty() ) {
     435        Node x=Q.front();
     436        Q.pop();
     437        for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
     438          Node y=g.runningNode(e);
     439          //growOrAugment grows if y is covered by the matching and
     440          //augments if not. In this latter case it returns 1.
     441          if (position[y]==C &&
     442              growOrAugment(y, x, ear, blossom, rep, tree, Q)) return;
     443        }
     444        R.push(x);
     445      }
     446     
     447      while ( !R.empty() ) {
     448        Node x=R.front();
     449        R.pop();
     450       
     451        for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
     452          Node y=g.runningNode(e);
     453
     454          if ( position[y] == D && blossom.find(x) != blossom.find(y) ) 
     455            //Recall that we have only one tree.
     456            shrink( x, y, ear, blossom, rep, tree, Q); 
     457       
     458          while ( !Q.empty() ) {
     459            Node z=Q.front();
     460            Q.pop();
     461            for( IncEdgeIt f(g,z); f!= INVALID; ++f ) {
     462              Node w=g.runningNode(f);
     463              //growOrAugment grows if y is covered by the matching and
     464              //augments if not. In this latter case it returns 1.
     465              if (position[w]==C &&
     466                  growOrAugment(w, z, ear, blossom, rep, tree, Q)) return;
     467            }
     468            R.push(z);
     469          }
     470        } //for e
     471      } // while ( !R.empty() )
     472    }
    330473
    331474    void normShrink(Node v, typename Graph::template NodeMap<Node>& ear, 
    332                     UFE& blossom, UFE& tree);
     475                    UFE& blossom, NV& rep, EFE& tree) {
     476      //We have one tree, which we grow and shrink. If we augment then we
     477      //return to the "for" cycle of runEdmonds().
     478   
     479      std::queue<Node> Q;   //queue of the unscanned nodes
     480      Q.push(v); 
     481      while ( !Q.empty() ) {
     482
     483        Node x=Q.front();
     484        Q.pop();
     485       
     486        for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
     487          Node y=g.runningNode(e);
     488             
     489          switch ( position[y] ) {
     490          case D:          //x and y must be in the same tree
     491            if ( blossom.find(x) != blossom.find(y))
     492              //x and y are in the same tree
     493              shrink(x, y, ear, blossom, rep, tree, Q);
     494            break;
     495          case C:
     496            //growOrAugment grows if y is covered by the matching and
     497            //augments if not. In this latter case it returns 1.
     498            if (growOrAugment(y, x, ear, blossom, rep, tree, Q)) return;
     499            break;
     500          default: break;
     501          }
     502        }
     503      }
     504    }
    333505
    334506    void shrink(Node x,Node y, typename Graph::template NodeMap<Node>& ear, 
    335                 UFE& blossom, UFE& tree,std::queue<Node>& Q);
     507                UFE& blossom, NV& rep, EFE& tree,std::queue<Node>& Q) {
     508      //x and y are the two adjacent vertices in two blossoms.
     509   
     510      typename Graph::template NodeMap<bool> path(g,false);
     511   
     512      Node b=rep[blossom.find(x)];
     513      path.set(b,true);
     514      b=_mate[b];
     515      while ( b!=INVALID ) {
     516        b=rep[blossom.find(ear[b])];
     517        path.set(b,true);
     518        b=_mate[b];
     519      } //we go until the root through bases of blossoms and odd vertices
     520   
     521      Node top=y;
     522      Node middle=rep[blossom.find(top)];
     523      Node bottom=x;
     524      while ( !path[middle] )
     525        shrinkStep(top, middle, bottom, ear, blossom, rep, tree, Q);
     526      //Until we arrive to a node on the path, we update blossom, tree
     527      //and the positions of the odd nodes.
     528   
     529      Node base=middle;
     530      top=x;
     531      middle=rep[blossom.find(top)];
     532      bottom=y;
     533      Node blossom_base=rep[blossom.find(base)];
     534      while ( middle!=blossom_base )
     535        shrinkStep(top, middle, bottom, ear, blossom, rep, tree, Q);
     536      //Until we arrive to a node on the path, we update blossom, tree
     537      //and the positions of the odd nodes.
     538   
     539      rep[blossom.find(base)] = base;
     540    }
    336541
    337542    void shrinkStep(Node& top, Node& middle, Node& bottom,
    338543                    typename Graph::template NodeMap<Node>& ear, 
    339                     UFE& blossom, UFE& tree, std::queue<Node>& Q);
     544                    UFE& blossom, NV& rep, EFE& tree, std::queue<Node>& Q) {
     545      //We traverse a blossom and update everything.
     546   
     547      ear.set(top,bottom);
     548      Node t=top;
     549      while ( t!=middle ) {
     550        Node u=_mate[t];
     551        t=ear[u];
     552        ear.set(t,u);
     553      }
     554      bottom=_mate[middle];
     555      position.set(bottom,D);
     556      Q.push(bottom);
     557      top=ear[bottom];         
     558      Node oldmiddle=middle;
     559      middle=rep[blossom.find(top)];
     560      tree.erase(bottom);
     561      tree.erase(oldmiddle);
     562      blossom.insert(bottom);
     563      blossom.join(bottom, oldmiddle);
     564      blossom.join(top, oldmiddle);
     565    }
     566
     567
    340568
    341569    bool growOrAugment(Node& y, Node& x, typename Graph::template
    342                        NodeMap<Node>& ear, UFE& blossom, UFE& tree,
    343                        std::queue<Node>& Q);
     570                       NodeMap<Node>& ear, UFE& blossom, NV& rep, EFE& tree,
     571                       std::queue<Node>& Q) {
     572      //x is in a blossom in the tree, y is outside. If y is covered by
     573      //the matching we grow, otherwise we augment. In this case we
     574      //return 1.
     575   
     576      if ( _mate[y]!=INVALID ) {       //grow
     577        ear.set(y,x);
     578        Node w=_mate[y];
     579        rep[blossom.insert(w)] = w;
     580        position.set(y,A);
     581        position.set(w,D);
     582        int t = tree.find(rep[blossom.find(x)]);
     583        tree.insert(y,t); 
     584        tree.insert(w,t); 
     585        Q.push(w);
     586      } else {                      //augment
     587        augment(x, ear, blossom, rep, tree);
     588        _mate.set(x,y);
     589        _mate.set(y,x);
     590        return true;
     591      }
     592      return false;
     593    }
    344594
    345595    void augment(Node x, typename Graph::template NodeMap<Node>& ear, 
    346                  UFE& blossom, UFE& tree);
     596                 UFE& blossom, NV& rep, EFE& tree) {
     597      Node v=_mate[x];
     598      while ( v!=INVALID ) {
     599       
     600        Node u=ear[v];
     601        _mate.set(v,u);
     602        Node tmp=v;
     603        v=_mate[u];
     604        _mate.set(u,tmp);
     605      }
     606      int y = tree.find(rep[blossom.find(x)]);
     607      for (typename EFE::ItemIt tit(tree, y); tit != INVALID; ++tit) {   
     608        if ( position[tit] == D ) {
     609          int b = blossom.find(tit);
     610          for (typename UFE::ItemIt bit(blossom, b); bit != INVALID; ++bit) {
     611            position.set(bit, C);
     612          }
     613          blossom.eraseClass(b);
     614        } else position.set(tit, C);
     615      }
     616      tree.eraseClass(y);
     617
     618    }
    347619
    348620  };
    349 
    350 
    351   // **********************************************************************
    352   //  IMPLEMENTATIONS
    353   // **********************************************************************
    354 
    355 
    356   template <typename Graph>
    357   void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template
    358                                       NodeMap<Node>& ear, UFE& blossom,
    359                                       UFE& tree) {
    360     //We have one tree which we grow, and also shrink but only if it cannot be
    361     //postponed. If we augment then we return to the "for" cycle of
    362     //runEdmonds().
    363 
    364     std::queue<Node> Q;   //queue of the totally unscanned nodes
    365     Q.push(v); 
    366     std::queue<Node> R;   
    367     //queue of the nodes which must be scanned for a possible shrink
    368      
    369     while ( !Q.empty() ) {
    370       Node x=Q.front();
    371       Q.pop();
    372       for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
    373         Node y=g.runningNode(e);
    374         //growOrAugment grows if y is covered by the matching and
    375         //augments if not. In this latter case it returns 1.
    376         if ( position[y]==C && growOrAugment(y, x, ear, blossom, tree, Q) )
    377           return;
    378       }
    379       R.push(x);
    380     }
    381      
    382     while ( !R.empty() ) {
    383       Node x=R.front();
    384       R.pop();
    385        
    386       for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
    387         Node y=g.runningNode(e);
    388 
    389         if ( position[y] == D && blossom.find(x) != blossom.find(y) ) 
    390           //Recall that we have only one tree.
    391           shrink( x, y, ear, blossom, tree, Q);
    392        
    393         while ( !Q.empty() ) {
    394           Node z=Q.front();
    395           Q.pop();
    396           for( IncEdgeIt f(g,z); f!= INVALID; ++f ) {
    397             Node w=g.runningNode(f);
    398             //growOrAugment grows if y is covered by the matching and
    399             //augments if not. In this latter case it returns 1.
    400             if ( position[w]==C && growOrAugment(w, z, ear, blossom, tree, Q) )
    401               return;
    402           }
    403           R.push(z);
    404         }
    405       } //for e
    406     } // while ( !R.empty() )
    407   }
    408 
    409 
    410   template <typename Graph>
    411   void MaxMatching<Graph>::normShrink(Node v,
    412                                       typename Graph::template
    413                                       NodeMap<Node>& ear, 
    414                                       UFE& blossom, UFE& tree) {
    415     //We have one tree, which we grow and shrink. If we augment then we
    416     //return to the "for" cycle of runEdmonds().
    417    
    418     std::queue<Node> Q;   //queue of the unscanned nodes
    419     Q.push(v); 
    420     while ( !Q.empty() ) {
    421 
    422       Node x=Q.front();
    423       Q.pop();
    424        
    425       for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
    426         Node y=g.runningNode(e);
    427              
    428         switch ( position[y] ) {
    429         case D:          //x and y must be in the same tree
    430           if ( blossom.find(x) != blossom.find(y) )
    431             //x and y are in the same tree
    432             shrink( x, y, ear, blossom, tree, Q);
    433           break;
    434         case C:
    435           //growOrAugment grows if y is covered by the matching and
    436           //augments if not. In this latter case it returns 1.
    437           if ( growOrAugment(y, x, ear, blossom, tree, Q) ) return;
    438           break;
    439         default: break;
    440         }
    441       }
    442     }
    443   }
    444  
    445 
    446   template <typename Graph>
    447     void MaxMatching<Graph>::shrink(Node x,Node y, typename
    448                                     Graph::template NodeMap<Node>& ear, 
    449                                     UFE& blossom, UFE& tree, std::queue<Node>& Q) {
    450     //x and y are the two adjacent vertices in two blossoms.
    451    
    452     typename Graph::template NodeMap<bool> path(g,false);
    453    
    454     Node b=blossom.find(x);
    455     path.set(b,true);
    456     b=_mate[b];
    457     while ( b!=INVALID ) {
    458       b=blossom.find(ear[b]);
    459       path.set(b,true);
    460       b=_mate[b];
    461     } //we go until the root through bases of blossoms and odd vertices
    462    
    463     Node top=y;
    464     Node middle=blossom.find(top);
    465     Node bottom=x;
    466     while ( !path[middle] )
    467       shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
    468     //Until we arrive to a node on the path, we update blossom, tree
    469     //and the positions of the odd nodes.
    470    
    471     Node base=middle;
    472     top=x;
    473     middle=blossom.find(top);
    474     bottom=y;
    475     Node blossom_base=blossom.find(base);
    476     while ( middle!=blossom_base )
    477       shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
    478     //Until we arrive to a node on the path, we update blossom, tree
    479     //and the positions of the odd nodes.
    480    
    481     blossom.makeRep(base);
    482   }
    483 
    484 
    485 
    486   template <typename Graph>
    487   void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom,
    488                                       typename Graph::template
    489                                       NodeMap<Node>& ear, 
    490                                       UFE& blossom, UFE& tree,
    491                                       std::queue<Node>& Q) {
    492     //We traverse a blossom and update everything.
    493    
    494     ear.set(top,bottom);
    495     Node t=top;
    496     while ( t!=middle ) {
    497       Node u=_mate[t];
    498       t=ear[u];
    499       ear.set(t,u);
    500     }
    501     bottom=_mate[middle];
    502     position.set(bottom,D);
    503     Q.push(bottom);
    504     top=ear[bottom];           
    505     Node oldmiddle=middle;
    506     middle=blossom.find(top);
    507     tree.erase(bottom);
    508     tree.erase(oldmiddle);
    509     blossom.insert(bottom);
    510     blossom.join(bottom, oldmiddle);
    511     blossom.join(top, oldmiddle);
    512   }
    513 
    514 
    515   template <typename Graph>
    516   bool MaxMatching<Graph>::growOrAugment(Node& y, Node& x, typename Graph::template
    517                                          NodeMap<Node>& ear, UFE& blossom, UFE& tree,
    518                                          std::queue<Node>& Q) {
    519     //x is in a blossom in the tree, y is outside. If y is covered by
    520     //the matching we grow, otherwise we augment. In this case we
    521     //return 1.
    522    
    523     if ( _mate[y]!=INVALID ) {       //grow
    524       ear.set(y,x);
    525       Node w=_mate[y];
    526       blossom.insert(w);
    527       position.set(y,A);
    528       position.set(w,D);
    529       tree.insert(y);
    530       tree.insert(w);
    531       tree.join(y,blossom.find(x)); 
    532       tree.join(w,y); 
    533       Q.push(w);
    534     } else {                      //augment
    535       augment(x, ear, blossom, tree);
    536       _mate.set(x,y);
    537       _mate.set(y,x);
    538       return true;
    539     }
    540     return false;
    541   }
    542  
    543 
    544   template <typename Graph>
    545   void MaxMatching<Graph>::augment(Node x,
    546                                    typename Graph::template NodeMap<Node>& ear, 
    547                                    UFE& blossom, UFE& tree) {
    548     Node v=_mate[x];
    549     while ( v!=INVALID ) {
    550        
    551       Node u=ear[v];
    552       _mate.set(v,u);
    553       Node tmp=v;
    554       v=_mate[u];
    555       _mate.set(u,tmp);
    556     }
    557     Node y=blossom.find(x);
    558     for (typename UFE::ItemIt tit(tree, y); tit != INVALID; ++tit) {   
    559       if ( position[tit] == D ) {
    560         for (typename UFE::ItemIt bit(blossom, tit); bit != INVALID; ++bit) { 
    561           position.set( bit ,C);
    562         }
    563         blossom.eraseClass(tit);
    564       } else position.set( tit ,C);
    565     }
    566     tree.eraseClass(y);
    567 
    568   }
    569 
    570621 
    571622} //END OF NAMESPACE LEMON
Note: See TracChangeset for help on using the changeset viewer.