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