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