lemon/max_matching.h
author deba
Fri, 29 Sep 2006 11:25:27 +0000
changeset 2223 590c1b663a27
parent 2042 bdc953f2a449
child 2308 cddae1c4fee6
permissions -rwxr-xr-x
Exporting interface to the Graph class
Some documentation improvements
jacint@1077
     1
/* -*- C++ -*-
jacint@1077
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
jacint@1077
     8
 *
jacint@1077
     9
 * Permission to use, modify and distribute this software is granted
jacint@1077
    10
 * provided that this copyright notice appears in all copies. For
jacint@1077
    11
 * precise terms see the accompanying LICENSE file.
jacint@1077
    12
 *
jacint@1077
    13
 * This software is provided "AS IS" with no warranty of any kind,
jacint@1077
    14
 * express or implied, and with no claim as to its suitability for any
jacint@1077
    15
 * purpose.
jacint@1077
    16
 *
jacint@1077
    17
 */
jacint@1077
    18
jacint@1077
    19
#ifndef LEMON_MAX_MATCHING_H
jacint@1077
    20
#define LEMON_MAX_MATCHING_H
jacint@1077
    21
jacint@1077
    22
#include <queue>
deba@1993
    23
#include <lemon/bits/invalid.h>
jacint@1093
    24
#include <lemon/unionfind.h>
jacint@1077
    25
#include <lemon/graph_utils.h>
jacint@1077
    26
deba@2042
    27
///\ingroup matching
jacint@1077
    28
///\file
deba@2042
    29
///\brief Maximum matching algorithm in undirected graph.
jacint@1077
    30
jacint@1077
    31
namespace lemon {
jacint@1077
    32
deba@2042
    33
  /// \ingroup matching
jacint@1077
    34
jacint@1077
    35
  ///Edmonds' alternating forest maximum matching algorithm.
jacint@1077
    36
jacint@1077
    37
  ///This class provides Edmonds' alternating forest matching
jacint@1077
    38
  ///algorithm. The starting matching (if any) can be passed to the
jacint@1077
    39
  ///algorithm using read-in functions \ref readNMapNode, \ref
jacint@1077
    40
  ///readNMapEdge or \ref readEMapBool depending on the container. The
jacint@1077
    41
  ///resulting maximum matching can be attained by write-out functions
jacint@1077
    42
  ///\ref writeNMapNode, \ref writeNMapEdge or \ref writeEMapBool
jacint@1077
    43
  ///depending on the preferred container. 
jacint@1077
    44
  ///
jacint@1077
    45
  ///The dual side of a matching is a map of the nodes to
jacint@1077
    46
  ///MaxMatching::pos_enum, having values D, A and C showing the
jacint@1077
    47
  ///Gallai-Edmonds decomposition of the graph. The nodes in D induce
jacint@1077
    48
  ///a graph with factor-critical components, the nodes in A form the
jacint@1077
    49
  ///barrier, and the nodes in C induce a graph having a perfect
jacint@1077
    50
  ///matching. This decomposition can be attained by calling \ref
jacint@1090
    51
  ///writePos after running the algorithm. 
jacint@1077
    52
  ///
jacint@1077
    53
  ///\param Graph The undirected graph type the algorithm runs on.
jacint@1077
    54
  ///
jacint@1077
    55
  ///\author Jacint Szabo  
jacint@1077
    56
  template <typename Graph>
jacint@1077
    57
  class MaxMatching {
jacint@1165
    58
jacint@1165
    59
  protected:
jacint@1165
    60
jacint@1077
    61
    typedef typename Graph::Node Node;
jacint@1077
    62
    typedef typename Graph::Edge Edge;
klao@1909
    63
    typedef typename Graph::UEdge UEdge;
klao@1909
    64
    typedef typename Graph::UEdgeIt UEdgeIt;
jacint@1077
    65
    typedef typename Graph::NodeIt NodeIt;
jacint@1077
    66
    typedef typename Graph::IncEdgeIt IncEdgeIt;
jacint@1077
    67
deba@2205
    68
    typedef typename Graph::template NodeMap<int> UFECrossRef;
deba@2205
    69
    typedef UnionFindEnum<Node, UFECrossRef> UFE;
jacint@1077
    70
jacint@1077
    71
  public:
jacint@1077
    72
    
jacint@1077
    73
    ///Indicates the Gallai-Edmonds decomposition of the graph.
jacint@1077
    74
jacint@1077
    75
    ///Indicates the Gallai-Edmonds decomposition of the graph, which
jacint@1077
    76
    ///shows an upper bound on the size of a maximum matching. The
jacint@1077
    77
    ///nodes with pos_enum \c D induce a graph with factor-critical
jacint@1077
    78
    ///components, the nodes in \c A form the canonical barrier, and the
jacint@1077
    79
    ///nodes in \c C induce a graph having a perfect matching. 
jacint@1077
    80
    enum pos_enum {
jacint@1077
    81
      D=0,
jacint@1077
    82
      A=1,
jacint@1077
    83
      C=2
jacint@1077
    84
    }; 
jacint@1077
    85
jacint@1165
    86
  protected:
jacint@1077
    87
jacint@1077
    88
    static const int HEUR_density=2;
jacint@1077
    89
    const Graph& g;
jacint@1093
    90
    typename Graph::template NodeMap<Node> _mate;
jacint@1077
    91
    typename Graph::template NodeMap<pos_enum> position;
jacint@1077
    92
     
jacint@1077
    93
  public:
jacint@1077
    94
    
jacint@1093
    95
    MaxMatching(const Graph& _g) : g(_g), _mate(_g,INVALID), position(_g) {}
jacint@1077
    96
jacint@1077
    97
    ///Runs Edmonds' algorithm.
jacint@1077
    98
jacint@1077
    99
    ///Runs Edmonds' algorithm for sparse graphs (number of edges <
jacint@1077
   100
    ///2*number of nodes), and a heuristical Edmonds' algorithm with a
jacint@1090
   101
    ///heuristic of postponing shrinks for dense graphs. 
alpar@1587
   102
    void run() {
klao@1909
   103
      if ( countUEdges(g) < HEUR_density*countNodes(g) ) {
alpar@1587
   104
	greedyMatching();
alpar@1587
   105
	runEdmonds(0);
alpar@1587
   106
      } else runEdmonds(1);
alpar@1587
   107
    }
alpar@1587
   108
jacint@1077
   109
jacint@1077
   110
    ///Runs Edmonds' algorithm.
jacint@1077
   111
    
jacint@1077
   112
    ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs
jacint@1077
   113
    ///Edmonds' algorithm with a heuristic of postponing shrinks,
jacint@1090
   114
    ///giving a faster algorithm for dense graphs.  
alpar@1587
   115
    void runEdmonds( int heur = 1 ) {
alpar@1587
   116
      
jacint@2023
   117
      //each vertex is put to C
alpar@1587
   118
      for(NodeIt v(g); v!=INVALID; ++v)
alpar@1587
   119
	position.set(v,C);      
alpar@1587
   120
      
alpar@1587
   121
      typename Graph::template NodeMap<Node> ear(g,INVALID); 
alpar@1587
   122
      //undefined for the base nodes of the blossoms (i.e. for the
alpar@1587
   123
      //representative elements of UFE blossom) and for the nodes in C 
alpar@1587
   124
      
deba@2205
   125
      UFECrossRef blossom_base(g);
alpar@1587
   126
      UFE blossom(blossom_base);
deba@2205
   127
deba@2205
   128
      UFECrossRef tree_base(g);
alpar@1587
   129
      UFE tree(tree_base);
deba@2205
   130
alpar@1587
   131
      //If these UFE's would be members of the class then also
alpar@1587
   132
      //blossom_base and tree_base should be a member.
alpar@1587
   133
      
jacint@2023
   134
      //We build only one tree and the other vertices uncovered by the
jacint@2023
   135
      //matching belong to C. (They can be considered as singleton
jacint@2023
   136
      //trees.) If this tree can be augmented or no more
jacint@2023
   137
      //grow/augmentation/shrink is possible then we return to this
jacint@2023
   138
      //"for" cycle.
alpar@1587
   139
      for(NodeIt v(g); v!=INVALID; ++v) {
alpar@1587
   140
	if ( position[v]==C && _mate[v]==INVALID ) {
alpar@1587
   141
	  blossom.insert(v);
alpar@1587
   142
	  tree.insert(v); 
alpar@1587
   143
	  position.set(v,D);
alpar@1587
   144
	  if ( heur == 1 ) lateShrink( v, ear, blossom, tree );
alpar@1587
   145
	  else normShrink( v, ear, blossom, tree );
alpar@1587
   146
	}
alpar@1587
   147
      }
alpar@1587
   148
    }
alpar@1587
   149
jacint@1077
   150
jacint@1077
   151
    ///Finds a greedy matching starting from the actual matching.
jacint@1077
   152
    
jacint@1077
   153
    ///Starting form the actual matching stored, it finds a maximal
jacint@1077
   154
    ///greedy matching.
alpar@1587
   155
    void greedyMatching() {
alpar@1587
   156
      for(NodeIt v(g); v!=INVALID; ++v)
alpar@1587
   157
	if ( _mate[v]==INVALID ) {
alpar@1587
   158
	  for( IncEdgeIt e(g,v); e!=INVALID ; ++e ) {
alpar@1587
   159
	    Node y=g.runningNode(e);
alpar@1587
   160
	    if ( _mate[y]==INVALID && y!=v ) {
alpar@1587
   161
	      _mate.set(v,y);
alpar@1587
   162
	      _mate.set(y,v);
alpar@1587
   163
	      break;
alpar@1587
   164
	    }
alpar@1587
   165
	  }
alpar@1587
   166
	} 
alpar@1587
   167
    }
jacint@1077
   168
jacint@1077
   169
    ///Returns the size of the actual matching stored.
jacint@1077
   170
jacint@1077
   171
    ///Returns the size of the actual matching stored. After \ref
jacint@1077
   172
    ///run() it returns the size of a maximum matching in the graph.
alpar@1587
   173
    int size() const {
alpar@1587
   174
      int s=0;
alpar@1587
   175
      for(NodeIt v(g); v!=INVALID; ++v) {
alpar@1587
   176
	if ( _mate[v]!=INVALID ) {
alpar@1587
   177
	  ++s;
alpar@1587
   178
	}
alpar@1587
   179
      }
alpar@1587
   180
      return s/2;
alpar@1587
   181
    }
alpar@1587
   182
jacint@1077
   183
jacint@1077
   184
    ///Resets the actual matching to the empty matching.
jacint@1077
   185
jacint@1077
   186
    ///Resets the actual matching to the empty matching.  
jacint@1077
   187
    ///
alpar@1587
   188
    void resetMatching() {
alpar@1587
   189
      for(NodeIt v(g); v!=INVALID; ++v)
alpar@1587
   190
	_mate.set(v,INVALID);      
alpar@1587
   191
    }
jacint@1077
   192
jacint@1093
   193
    ///Returns the mate of a node in the actual matching.
jacint@1093
   194
jacint@1093
   195
    ///Returns the mate of a \c node in the actual matching. 
jacint@1093
   196
    ///Returns INVALID if the \c node is not covered by the actual matching. 
jacint@1093
   197
    Node mate(Node& node) const {
jacint@1093
   198
      return _mate[node];
jacint@1093
   199
    } 
jacint@1093
   200
jacint@1165
   201
    ///Reads a matching from a \c Node valued \c Node map.
jacint@1077
   202
jacint@1165
   203
    ///Reads a matching from a \c Node valued \c Node map. This map
jacint@1165
   204
    ///must be \e symmetric, i.e. if \c map[u]==v then \c map[v]==u
jacint@1165
   205
    ///must hold, and \c uv will be an edge of the matching.
jacint@1077
   206
    template<typename NMapN>
jacint@1077
   207
    void readNMapNode(NMapN& map) {
jacint@1077
   208
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@1093
   209
	_mate.set(v,map[v]);   
jacint@1077
   210
      } 
jacint@1077
   211
    } 
jacint@1077
   212
    
jacint@1165
   213
    ///Writes the stored matching to a \c Node valued \c Node map.
jacint@1077
   214
jacint@1165
   215
    ///Writes the stored matching to a \c Node valued \c Node map. The
jacint@1077
   216
    ///resulting map will be \e symmetric, i.e. if \c map[u]==v then \c
jacint@1077
   217
    ///map[v]==u will hold, and now \c uv is an edge of the matching.
jacint@1077
   218
    template<typename NMapN>
jacint@1077
   219
    void writeNMapNode (NMapN& map) const {
jacint@1077
   220
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@1093
   221
	map.set(v,_mate[v]);   
jacint@1077
   222
      } 
jacint@1077
   223
    } 
jacint@1077
   224
klao@1909
   225
    ///Reads a matching from an \c UEdge valued \c Node map.
jacint@1077
   226
klao@1909
   227
    ///Reads a matching from an \c UEdge valued \c Node map. \c
klao@1909
   228
    ///map[v] must be an \c UEdge incident to \c v. This map must
jacint@1165
   229
    ///have the property that if \c g.oppositeNode(u,map[u])==v then
jacint@1165
   230
    ///\c \c g.oppositeNode(v,map[v])==u holds, and now some edge
marci@1172
   231
    ///joining \c u to \c v will be an edge of the matching.
jacint@1077
   232
    template<typename NMapE>
jacint@1077
   233
    void readNMapEdge(NMapE& map) {
jacint@2023
   234
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@2023
   235
	UEdge e=map[v];
jacint@1165
   236
	if ( e!=INVALID )
jacint@1166
   237
	  _mate.set(v,g.oppositeNode(v,e));
jacint@1077
   238
      } 
jacint@1077
   239
    } 
jacint@1077
   240
    
klao@1909
   241
    ///Writes the matching stored to an \c UEdge valued \c Node map.
jacint@1077
   242
klao@1909
   243
    ///Writes the stored matching to an \c UEdge valued \c Node
klao@1909
   244
    ///map. \c map[v] will be an \c UEdge incident to \c v. This
jacint@1165
   245
    ///map will have the property that if \c g.oppositeNode(u,map[u])
jacint@1165
   246
    ///== v then \c map[u]==map[v] holds, and now this edge is an edge
jacint@1165
   247
    ///of the matching.
jacint@1077
   248
    template<typename NMapE>
jacint@1077
   249
    void writeNMapEdge (NMapE& map)  const {
jacint@1077
   250
      typename Graph::template NodeMap<bool> todo(g,true); 
jacint@1077
   251
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@1093
   252
	if ( todo[v] && _mate[v]!=INVALID ) {
jacint@1093
   253
	  Node u=_mate[v];
jacint@1077
   254
	  for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
klao@1158
   255
	    if ( g.runningNode(e) == u ) {
jacint@1077
   256
	      map.set(u,e);
jacint@1077
   257
	      map.set(v,e);
jacint@1077
   258
	      todo.set(u,false);
jacint@1077
   259
	      todo.set(v,false);
jacint@1077
   260
	      break;
jacint@1077
   261
	    }
jacint@1077
   262
	  }
jacint@1077
   263
	}
jacint@1077
   264
      } 
jacint@1077
   265
    }
jacint@1077
   266
jacint@1077
   267
jacint@1165
   268
    ///Reads a matching from a \c bool valued \c Edge map.
jacint@1077
   269
    
jacint@1165
   270
    ///Reads a matching from a \c bool valued \c Edge map. This map
jacint@1165
   271
    ///must have the property that there are no two incident edges \c
jacint@1165
   272
    ///e, \c f with \c map[e]==map[f]==true. The edges \c e with \c
jacint@1077
   273
    ///map[e]==true form the matching.
jacint@1077
   274
    template<typename EMapB>
jacint@1077
   275
    void readEMapBool(EMapB& map) {
klao@1909
   276
      for(UEdgeIt e(g); e!=INVALID; ++e) {
jacint@1077
   277
	if ( map[e] ) {
jacint@1077
   278
	  Node u=g.source(e);	  
jacint@1077
   279
	  Node v=g.target(e);
jacint@1093
   280
	  _mate.set(u,v);
jacint@1093
   281
	  _mate.set(v,u);
jacint@1077
   282
	} 
jacint@1077
   283
      } 
jacint@1077
   284
    }
jacint@1077
   285
jacint@1077
   286
jacint@1165
   287
    ///Writes the matching stored to a \c bool valued \c Edge map.
jacint@1077
   288
jacint@1165
   289
    ///Writes the matching stored to a \c bool valued \c Edge
jacint@1165
   290
    ///map. This map will have the property that there are no two
jacint@1165
   291
    ///incident edges \c e, \c f with \c map[e]==map[f]==true. The
jacint@1165
   292
    ///edges \c e with \c map[e]==true form the matching.
jacint@1077
   293
    template<typename EMapB>
jacint@1077
   294
    void writeEMapBool (EMapB& map) const {
klao@1909
   295
      for(UEdgeIt e(g); e!=INVALID; ++e) map.set(e,false);
jacint@1077
   296
jacint@1077
   297
      typename Graph::template NodeMap<bool> todo(g,true); 
jacint@1077
   298
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@1093
   299
	if ( todo[v] && _mate[v]!=INVALID ) {
jacint@1093
   300
	  Node u=_mate[v];
jacint@1077
   301
	  for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
klao@1158
   302
	    if ( g.runningNode(e) == u ) {
jacint@1077
   303
	      map.set(e,true);
jacint@1077
   304
	      todo.set(u,false);
jacint@1077
   305
	      todo.set(v,false);
jacint@1077
   306
	      break;
jacint@1077
   307
	    }
jacint@1077
   308
	  }
jacint@1077
   309
	}
jacint@1077
   310
      } 
jacint@1077
   311
    }
jacint@1077
   312
jacint@1077
   313
jacint@1077
   314
    ///Writes the canonical decomposition of the graph after running
jacint@1077
   315
    ///the algorithm.
jacint@1077
   316
jacint@1090
   317
    ///After calling any run methods of the class, it writes the
jacint@1090
   318
    ///Gallai-Edmonds canonical decomposition of the graph. \c map
jacint@1090
   319
    ///must be a node map of \ref pos_enum 's.
jacint@1077
   320
    template<typename NMapEnum>
jacint@1077
   321
    void writePos (NMapEnum& map) const {
jacint@1077
   322
      for(NodeIt v(g); v!=INVALID; ++v)  map.set(v,position[v]);
jacint@1077
   323
    }
jacint@1077
   324
jacint@1077
   325
  private: 
jacint@1077
   326
jacint@1165
   327
 
jacint@1077
   328
    void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   329
		    UFE& blossom, UFE& tree);
jacint@1077
   330
alpar@1234
   331
    void normShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   332
		    UFE& blossom, UFE& tree);
jacint@1077
   333
jacint@2023
   334
    void shrink(Node x,Node y, typename Graph::template NodeMap<Node>& ear,  
jacint@2023
   335
		UFE& blossom, UFE& tree,std::queue<Node>& Q);
jacint@1077
   336
alpar@1234
   337
    void shrinkStep(Node& top, Node& middle, Node& bottom,
alpar@1234
   338
		    typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   339
		    UFE& blossom, UFE& tree, std::queue<Node>& Q);
jacint@1077
   340
jacint@2023
   341
    bool growOrAugment(Node& y, Node& x, typename Graph::template 
jacint@2023
   342
		       NodeMap<Node>& ear, UFE& blossom, UFE& tree, 
jacint@2023
   343
		       std::queue<Node>& Q);
jacint@2023
   344
alpar@1234
   345
    void augment(Node x, typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   346
		 UFE& blossom, UFE& tree);
jacint@1077
   347
jacint@1077
   348
  };
jacint@1077
   349
jacint@1077
   350
jacint@1077
   351
  // **********************************************************************
jacint@1077
   352
  //  IMPLEMENTATIONS
jacint@1077
   353
  // **********************************************************************
jacint@1077
   354
jacint@1077
   355
jacint@1077
   356
  template <typename Graph>
jacint@2023
   357
  void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template 
jacint@2023
   358
				      NodeMap<Node>& ear, UFE& blossom, UFE& tree) {
jacint@2023
   359
    //We have one tree which we grow, and also shrink but only if it cannot be
jacint@2023
   360
    //postponed. If we augment then we return to the "for" cycle of
jacint@2023
   361
    //runEdmonds().
jacint@1077
   362
jacint@1077
   363
    std::queue<Node> Q;   //queue of the totally unscanned nodes
jacint@1077
   364
    Q.push(v);  
jacint@1077
   365
    std::queue<Node> R;   
jacint@1077
   366
    //queue of the nodes which must be scanned for a possible shrink
jacint@1077
   367
      
jacint@1077
   368
    while ( !Q.empty() ) {
jacint@1077
   369
      Node x=Q.front();
jacint@1077
   370
      Q.pop();
jacint@2023
   371
      for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
jacint@2023
   372
	Node y=g.runningNode(e);
jacint@2023
   373
	//growOrAugment grows if y is covered by the matching and
jacint@2023
   374
	//augments if not. In this latter case it returns 1.
jacint@2023
   375
	if ( position[y]==C && growOrAugment(y, x, ear, blossom, tree, Q) ) return;
jacint@2023
   376
      }
jacint@2023
   377
      R.push(x);
jacint@1077
   378
    }
jacint@1077
   379
      
jacint@1077
   380
    while ( !R.empty() ) {
jacint@1077
   381
      Node x=R.front();
jacint@1077
   382
      R.pop();
jacint@1077
   383
	
jacint@1077
   384
      for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
klao@1158
   385
	Node y=g.runningNode(e);
jacint@1077
   386
jacint@2023
   387
	if ( position[y] == D && blossom.find(x) != blossom.find(y) )  
jacint@2023
   388
	  //Recall that we have only one tree.
jacint@2023
   389
	  shrink( x, y, ear, blossom, tree, Q);	
jacint@1077
   390
	
jacint@1077
   391
	while ( !Q.empty() ) {
jacint@1077
   392
	  Node x=Q.front();
jacint@1077
   393
	  Q.pop();
jacint@2023
   394
	  for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
jacint@2023
   395
	    Node y=g.runningNode(e);
jacint@2023
   396
	    //growOrAugment grows if y is covered by the matching and
jacint@2023
   397
	    //augments if not. In this latter case it returns 1.
jacint@2023
   398
	    if ( position[y]==C && growOrAugment(y, x, ear, blossom, tree, Q) ) return;
jacint@2023
   399
	  }
jacint@2023
   400
	  R.push(x);
jacint@1077
   401
	}
jacint@1077
   402
      } //for e
jacint@1077
   403
    } // while ( !R.empty() )
jacint@1077
   404
  }
jacint@1077
   405
jacint@1077
   406
jacint@1077
   407
  template <typename Graph>
alpar@1234
   408
  void MaxMatching<Graph>::normShrink(Node v,
alpar@1234
   409
				      typename Graph::template
alpar@1234
   410
				      NodeMap<Node>& ear,  
jacint@1077
   411
				      UFE& blossom, UFE& tree) {
jacint@2023
   412
    //We have one tree, which we grow and shrink. If we augment then we
jacint@2023
   413
    //return to the "for" cycle of runEdmonds().
jacint@2023
   414
    
jacint@1077
   415
    std::queue<Node> Q;   //queue of the unscanned nodes
jacint@1077
   416
    Q.push(v);  
jacint@1077
   417
    while ( !Q.empty() ) {
jacint@1077
   418
jacint@1077
   419
      Node x=Q.front();
jacint@1077
   420
      Q.pop();
jacint@1077
   421
	
jacint@1077
   422
      for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
klao@1158
   423
	Node y=g.runningNode(e);
jacint@1077
   424
	      
jacint@1077
   425
	switch ( position[y] ) {
jacint@1077
   426
	case D:          //x and y must be in the same tree
jacint@2023
   427
	  if ( blossom.find(x) != blossom.find(y) )
jacint@2023
   428
	    //x and y are in the same tree
jacint@2023
   429
	    shrink( x, y, ear, blossom, tree, Q);
jacint@1077
   430
	  break;
jacint@1077
   431
	case C:
jacint@2023
   432
	  //growOrAugment grows if y is covered by the matching and
jacint@2023
   433
	  //augments if not. In this latter case it returns 1.
jacint@2023
   434
	  if ( growOrAugment(y, x, ear, blossom, tree, Q) ) return;
jacint@1077
   435
	  break;
jacint@1077
   436
	default: break;
jacint@2023
   437
       	}
jacint@1077
   438
      }
jacint@1077
   439
    }
jacint@1077
   440
  }
jacint@2023
   441
  
jacint@1077
   442
jacint@1077
   443
  template <typename Graph>
jacint@2023
   444
    void MaxMatching<Graph>::shrink(Node x,Node y, typename 
jacint@2023
   445
				    Graph::template NodeMap<Node>& ear,  
jacint@2023
   446
				    UFE& blossom, UFE& tree, std::queue<Node>& Q) {
jacint@2023
   447
    //x and y are the two adjacent vertices in two blossoms.
jacint@2023
   448
   
jacint@2023
   449
    typename Graph::template NodeMap<bool> path(g,false);
jacint@2023
   450
    
jacint@2023
   451
    Node b=blossom.find(x);
jacint@2023
   452
    path.set(b,true);
jacint@2023
   453
    b=_mate[b];
jacint@2023
   454
    while ( b!=INVALID ) { 
jacint@2023
   455
      b=blossom.find(ear[b]);
jacint@2023
   456
      path.set(b,true);
jacint@2023
   457
      b=_mate[b];
jacint@2023
   458
    } //we go until the root through bases of blossoms and odd vertices
jacint@2023
   459
    
jacint@2023
   460
    Node top=y;
jacint@2023
   461
    Node middle=blossom.find(top);
jacint@2023
   462
    Node bottom=x;
jacint@2023
   463
    while ( !path[middle] )
jacint@2023
   464
      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
jacint@2023
   465
    //Until we arrive to a node on the path, we update blossom, tree
jacint@2023
   466
    //and the positions of the odd nodes.
jacint@2023
   467
    
jacint@2023
   468
    Node base=middle;
jacint@2023
   469
    top=x;
jacint@2023
   470
    middle=blossom.find(top);
jacint@2023
   471
    bottom=y;
jacint@2023
   472
    Node blossom_base=blossom.find(base);
jacint@2023
   473
    while ( middle!=blossom_base )
jacint@2023
   474
      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
jacint@2023
   475
    //Until we arrive to a node on the path, we update blossom, tree
jacint@2023
   476
    //and the positions of the odd nodes.
jacint@2023
   477
    
jacint@2023
   478
    blossom.makeRep(base);
jacint@1077
   479
  }
jacint@1077
   480
jacint@2023
   481
jacint@2023
   482
jacint@1077
   483
  template <typename Graph>
alpar@1234
   484
  void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom,
alpar@1234
   485
				      typename Graph::template
alpar@1234
   486
				      NodeMap<Node>& ear,  
alpar@1234
   487
				      UFE& blossom, UFE& tree,
alpar@1234
   488
				      std::queue<Node>& Q) {
jacint@2023
   489
    //We traverse a blossom and update everything.
jacint@2023
   490
    
jacint@1077
   491
    ear.set(top,bottom);
jacint@1077
   492
    Node t=top;
jacint@1077
   493
    while ( t!=middle ) {
jacint@1093
   494
      Node u=_mate[t];
jacint@1077
   495
      t=ear[u];
jacint@1077
   496
      ear.set(t,u);
jacint@1077
   497
    } 
jacint@1093
   498
    bottom=_mate[middle];
jacint@1077
   499
    position.set(bottom,D);
jacint@1077
   500
    Q.push(bottom);
jacint@1077
   501
    top=ear[bottom];		
jacint@1077
   502
    Node oldmiddle=middle;
jacint@1077
   503
    middle=blossom.find(top);
jacint@1077
   504
    tree.erase(bottom);
jacint@1077
   505
    tree.erase(oldmiddle);
jacint@1077
   506
    blossom.insert(bottom);
jacint@1077
   507
    blossom.join(bottom, oldmiddle);
jacint@1077
   508
    blossom.join(top, oldmiddle);
jacint@1077
   509
  }
jacint@1077
   510
jacint@2023
   511
jacint@2023
   512
  template <typename Graph>
jacint@2023
   513
  bool MaxMatching<Graph>::growOrAugment(Node& y, Node& x, typename Graph::template
jacint@2023
   514
					 NodeMap<Node>& ear, UFE& blossom, UFE& tree,
jacint@2023
   515
					 std::queue<Node>& Q) {
jacint@2023
   516
    //x is in a blossom in the tree, y is outside. If y is covered by
jacint@2023
   517
    //the matching we grow, otherwise we augment. In this case we
jacint@2023
   518
    //return 1.
jacint@2023
   519
    
jacint@2023
   520
    if ( _mate[y]!=INVALID ) {       //grow
jacint@2023
   521
      ear.set(y,x);
jacint@2023
   522
      Node w=_mate[y];
jacint@2023
   523
      blossom.insert(w);
jacint@2023
   524
      position.set(y,A);
jacint@2023
   525
      position.set(w,D);
jacint@2023
   526
      tree.insert(y);
jacint@2023
   527
      tree.insert(w);
jacint@2023
   528
      tree.join(y,blossom.find(x));  
jacint@2023
   529
      tree.join(w,y);  
jacint@2023
   530
      Q.push(w);
jacint@2023
   531
    } else {                      //augment 
jacint@2023
   532
      augment(x, ear, blossom, tree);
jacint@2023
   533
      _mate.set(x,y);
jacint@2023
   534
      _mate.set(y,x);
jacint@2023
   535
      return true;
jacint@2023
   536
    }
jacint@2023
   537
    return false;
jacint@2023
   538
  }
jacint@2023
   539
  
jacint@2023
   540
jacint@1077
   541
  template <typename Graph>
alpar@1234
   542
  void MaxMatching<Graph>::augment(Node x,
alpar@1234
   543
				   typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   544
				   UFE& blossom, UFE& tree) { 
jacint@1093
   545
    Node v=_mate[x];
jacint@1077
   546
    while ( v!=INVALID ) {
jacint@1077
   547
	
jacint@1077
   548
      Node u=ear[v];
jacint@1093
   549
      _mate.set(v,u);
jacint@1077
   550
      Node tmp=v;
jacint@1093
   551
      v=_mate[u];
jacint@1093
   552
      _mate.set(u,tmp);
jacint@1077
   553
    }
jacint@2023
   554
    Node y=blossom.find(x);
deba@2205
   555
    for (typename UFE::ItemIt tit(tree, y); tit != INVALID; ++tit) {   
deba@2205
   556
      if ( position[tit] == D ) {
deba@2205
   557
	for (typename UFE::ItemIt bit(blossom, tit); bit != INVALID; ++bit) {  
deba@2205
   558
	  position.set( bit ,C);
jacint@1077
   559
	}
deba@2205
   560
	blossom.eraseClass(tit);
deba@2205
   561
      } else position.set( tit ,C);
jacint@1077
   562
    }
jacint@2023
   563
    tree.eraseClass(y);
jacint@1077
   564
jacint@1077
   565
  }
jacint@1077
   566
jacint@1077
   567
  
jacint@1077
   568
} //END OF NAMESPACE LEMON
jacint@1077
   569
jacint@1165
   570
#endif //LEMON_MAX_MATCHING_H