lemon/max_matching.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1435 8e85e6bbefdf
child 1875 98698b69a902
permissions -rwxr-xr-x
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
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. 
alpar@1587
   100
    void run() {
alpar@1587
   101
      if ( countUndirEdges(g) < HEUR_density*countNodes(g) ) {
alpar@1587
   102
	greedyMatching();
alpar@1587
   103
	runEdmonds(0);
alpar@1587
   104
      } else runEdmonds(1);
alpar@1587
   105
    }
alpar@1587
   106
jacint@1077
   107
jacint@1077
   108
    ///Runs Edmonds' algorithm.
jacint@1077
   109
    
jacint@1077
   110
    ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs
jacint@1077
   111
    ///Edmonds' algorithm with a heuristic of postponing shrinks,
jacint@1090
   112
    ///giving a faster algorithm for dense graphs.  
alpar@1587
   113
    void runEdmonds( int heur = 1 ) {
alpar@1587
   114
      
alpar@1587
   115
      for(NodeIt v(g); v!=INVALID; ++v)
alpar@1587
   116
	position.set(v,C);      
alpar@1587
   117
      
alpar@1587
   118
      typename Graph::template NodeMap<Node> ear(g,INVALID); 
alpar@1587
   119
      //undefined for the base nodes of the blossoms (i.e. for the
alpar@1587
   120
      //representative elements of UFE blossom) and for the nodes in C 
alpar@1587
   121
      
alpar@1587
   122
      typename UFE::MapType blossom_base(g);
alpar@1587
   123
      UFE blossom(blossom_base);
alpar@1587
   124
      typename UFE::MapType tree_base(g);
alpar@1587
   125
      UFE tree(tree_base);
alpar@1587
   126
      //If these UFE's would be members of the class then also
alpar@1587
   127
      //blossom_base and tree_base should be a member.
alpar@1587
   128
      
alpar@1587
   129
      for(NodeIt v(g); v!=INVALID; ++v) {
alpar@1587
   130
	if ( position[v]==C && _mate[v]==INVALID ) {
alpar@1587
   131
	  blossom.insert(v);
alpar@1587
   132
	  tree.insert(v); 
alpar@1587
   133
	  position.set(v,D);
alpar@1587
   134
	  if ( heur == 1 ) lateShrink( v, ear, blossom, tree );
alpar@1587
   135
	  else normShrink( v, ear, blossom, tree );
alpar@1587
   136
	}
alpar@1587
   137
      }
alpar@1587
   138
    }
alpar@1587
   139
jacint@1077
   140
jacint@1077
   141
    ///Finds a greedy matching starting from the actual matching.
jacint@1077
   142
    
jacint@1077
   143
    ///Starting form the actual matching stored, it finds a maximal
jacint@1077
   144
    ///greedy matching.
alpar@1587
   145
    void greedyMatching() {
alpar@1587
   146
      for(NodeIt v(g); v!=INVALID; ++v)
alpar@1587
   147
	if ( _mate[v]==INVALID ) {
alpar@1587
   148
	  for( IncEdgeIt e(g,v); e!=INVALID ; ++e ) {
alpar@1587
   149
	    Node y=g.runningNode(e);
alpar@1587
   150
	    if ( _mate[y]==INVALID && y!=v ) {
alpar@1587
   151
	      _mate.set(v,y);
alpar@1587
   152
	      _mate.set(y,v);
alpar@1587
   153
	      break;
alpar@1587
   154
	    }
alpar@1587
   155
	  }
alpar@1587
   156
	} 
alpar@1587
   157
    }
jacint@1077
   158
jacint@1077
   159
    ///Returns the size of the actual matching stored.
jacint@1077
   160
jacint@1077
   161
    ///Returns the size of the actual matching stored. After \ref
jacint@1077
   162
    ///run() it returns the size of a maximum matching in the graph.
alpar@1587
   163
    int size() const {
alpar@1587
   164
      int s=0;
alpar@1587
   165
      for(NodeIt v(g); v!=INVALID; ++v) {
alpar@1587
   166
	if ( _mate[v]!=INVALID ) {
alpar@1587
   167
	  ++s;
alpar@1587
   168
	}
alpar@1587
   169
      }
alpar@1587
   170
      return s/2;
alpar@1587
   171
    }
alpar@1587
   172
jacint@1077
   173
jacint@1077
   174
    ///Resets the actual matching to the empty matching.
jacint@1077
   175
jacint@1077
   176
    ///Resets the actual matching to the empty matching.  
jacint@1077
   177
    ///
alpar@1587
   178
    void resetMatching() {
alpar@1587
   179
      for(NodeIt v(g); v!=INVALID; ++v)
alpar@1587
   180
	_mate.set(v,INVALID);      
alpar@1587
   181
    }
jacint@1077
   182
jacint@1093
   183
    ///Returns the mate of a node in the actual matching.
jacint@1093
   184
jacint@1093
   185
    ///Returns the mate of a \c node in the actual matching. 
jacint@1093
   186
    ///Returns INVALID if the \c node is not covered by the actual matching. 
jacint@1093
   187
    Node mate(Node& node) const {
jacint@1093
   188
      return _mate[node];
jacint@1093
   189
    } 
jacint@1093
   190
jacint@1165
   191
    ///Reads a matching from a \c Node valued \c Node map.
jacint@1077
   192
jacint@1165
   193
    ///Reads a matching from a \c Node valued \c Node map. This map
jacint@1165
   194
    ///must be \e symmetric, i.e. if \c map[u]==v then \c map[v]==u
jacint@1165
   195
    ///must hold, and \c uv will be an edge of the matching.
jacint@1077
   196
    template<typename NMapN>
jacint@1077
   197
    void readNMapNode(NMapN& map) {
jacint@1077
   198
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@1093
   199
	_mate.set(v,map[v]);   
jacint@1077
   200
      } 
jacint@1077
   201
    } 
jacint@1077
   202
    
jacint@1165
   203
    ///Writes the stored matching to a \c Node valued \c Node map.
jacint@1077
   204
jacint@1165
   205
    ///Writes the stored matching to a \c Node valued \c Node map. The
jacint@1077
   206
    ///resulting map will be \e symmetric, i.e. if \c map[u]==v then \c
jacint@1077
   207
    ///map[v]==u will hold, and now \c uv is an edge of the matching.
jacint@1077
   208
    template<typename NMapN>
jacint@1077
   209
    void writeNMapNode (NMapN& map) const {
jacint@1077
   210
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@1093
   211
	map.set(v,_mate[v]);   
jacint@1077
   212
      } 
jacint@1077
   213
    } 
jacint@1077
   214
jacint@1165
   215
    ///Reads a matching from an \c UndirEdge valued \c Node map.
jacint@1077
   216
jacint@1165
   217
    ///Reads a matching from an \c UndirEdge valued \c Node map. \c
jacint@1165
   218
    ///map[v] must be an \c UndirEdge incident to \c v. This map must
jacint@1165
   219
    ///have the property that if \c g.oppositeNode(u,map[u])==v then
jacint@1165
   220
    ///\c \c g.oppositeNode(v,map[v])==u holds, and now some edge
marci@1172
   221
    ///joining \c u to \c v will be an edge of the matching.
jacint@1077
   222
    template<typename NMapE>
jacint@1077
   223
    void readNMapEdge(NMapE& map) {
jacint@1077
   224
     for(NodeIt v(g); v!=INVALID; ++v) {
alpar@1177
   225
       UndirEdge e=map[v];
jacint@1165
   226
	if ( e!=INVALID )
jacint@1166
   227
	  _mate.set(v,g.oppositeNode(v,e));
jacint@1077
   228
      } 
jacint@1077
   229
    } 
jacint@1077
   230
    
jacint@1165
   231
    ///Writes the matching stored to an \c UndirEdge valued \c Node map.
jacint@1077
   232
jacint@1165
   233
    ///Writes the stored matching to an \c UndirEdge valued \c Node
jacint@1165
   234
    ///map. \c map[v] will be an \c UndirEdge incident to \c v. This
jacint@1165
   235
    ///map will have the property that if \c g.oppositeNode(u,map[u])
jacint@1165
   236
    ///== v then \c map[u]==map[v] holds, and now this edge is an edge
jacint@1165
   237
    ///of the matching.
jacint@1077
   238
    template<typename NMapE>
jacint@1077
   239
    void writeNMapEdge (NMapE& map)  const {
jacint@1077
   240
      typename Graph::template NodeMap<bool> todo(g,true); 
jacint@1077
   241
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@1093
   242
	if ( todo[v] && _mate[v]!=INVALID ) {
jacint@1093
   243
	  Node u=_mate[v];
jacint@1077
   244
	  for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
klao@1158
   245
	    if ( g.runningNode(e) == u ) {
jacint@1077
   246
	      map.set(u,e);
jacint@1077
   247
	      map.set(v,e);
jacint@1077
   248
	      todo.set(u,false);
jacint@1077
   249
	      todo.set(v,false);
jacint@1077
   250
	      break;
jacint@1077
   251
	    }
jacint@1077
   252
	  }
jacint@1077
   253
	}
jacint@1077
   254
      } 
jacint@1077
   255
    }
jacint@1077
   256
jacint@1077
   257
jacint@1165
   258
    ///Reads a matching from a \c bool valued \c Edge map.
jacint@1077
   259
    
jacint@1165
   260
    ///Reads a matching from a \c bool valued \c Edge map. This map
jacint@1165
   261
    ///must have the property that there are no two incident edges \c
jacint@1165
   262
    ///e, \c f with \c map[e]==map[f]==true. The edges \c e with \c
jacint@1077
   263
    ///map[e]==true form the matching.
jacint@1077
   264
    template<typename EMapB>
jacint@1077
   265
    void readEMapBool(EMapB& map) {
jacint@1077
   266
      for(UndirEdgeIt e(g); e!=INVALID; ++e) {
jacint@1077
   267
	if ( map[e] ) {
jacint@1077
   268
	  Node u=g.source(e);	  
jacint@1077
   269
	  Node v=g.target(e);
jacint@1093
   270
	  _mate.set(u,v);
jacint@1093
   271
	  _mate.set(v,u);
jacint@1077
   272
	} 
jacint@1077
   273
      } 
jacint@1077
   274
    }
jacint@1077
   275
jacint@1077
   276
jacint@1165
   277
    ///Writes the matching stored to a \c bool valued \c Edge map.
jacint@1077
   278
jacint@1165
   279
    ///Writes the matching stored to a \c bool valued \c Edge
jacint@1165
   280
    ///map. This map will have the property that there are no two
jacint@1165
   281
    ///incident edges \c e, \c f with \c map[e]==map[f]==true. The
jacint@1165
   282
    ///edges \c e with \c map[e]==true form the matching.
jacint@1077
   283
    template<typename EMapB>
jacint@1077
   284
    void writeEMapBool (EMapB& map) const {
jacint@1077
   285
      for(UndirEdgeIt e(g); e!=INVALID; ++e) map.set(e,false);
jacint@1077
   286
jacint@1077
   287
      typename Graph::template NodeMap<bool> todo(g,true); 
jacint@1077
   288
      for(NodeIt v(g); v!=INVALID; ++v) {
jacint@1093
   289
	if ( todo[v] && _mate[v]!=INVALID ) {
jacint@1093
   290
	  Node u=_mate[v];
jacint@1077
   291
	  for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
klao@1158
   292
	    if ( g.runningNode(e) == u ) {
jacint@1077
   293
	      map.set(e,true);
jacint@1077
   294
	      todo.set(u,false);
jacint@1077
   295
	      todo.set(v,false);
jacint@1077
   296
	      break;
jacint@1077
   297
	    }
jacint@1077
   298
	  }
jacint@1077
   299
	}
jacint@1077
   300
      } 
jacint@1077
   301
    }
jacint@1077
   302
jacint@1077
   303
jacint@1077
   304
    ///Writes the canonical decomposition of the graph after running
jacint@1077
   305
    ///the algorithm.
jacint@1077
   306
jacint@1090
   307
    ///After calling any run methods of the class, it writes the
jacint@1090
   308
    ///Gallai-Edmonds canonical decomposition of the graph. \c map
jacint@1090
   309
    ///must be a node map of \ref pos_enum 's.
jacint@1077
   310
    template<typename NMapEnum>
jacint@1077
   311
    void writePos (NMapEnum& map) const {
jacint@1077
   312
      for(NodeIt v(g); v!=INVALID; ++v)  map.set(v,position[v]);
jacint@1077
   313
    }
jacint@1077
   314
jacint@1077
   315
  private: 
jacint@1077
   316
jacint@1165
   317
 
jacint@1077
   318
    void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   319
		    UFE& blossom, UFE& tree);
jacint@1077
   320
alpar@1234
   321
    void normShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   322
		    UFE& blossom, UFE& tree);
jacint@1077
   323
alpar@1234
   324
    bool noShrinkStep(Node x, typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   325
		      UFE& blossom, UFE& tree, std::queue<Node>& Q);
jacint@1077
   326
alpar@1234
   327
    void shrinkStep(Node& top, Node& middle, Node& bottom,
alpar@1234
   328
		    typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   329
		    UFE& blossom, UFE& tree, std::queue<Node>& Q);
jacint@1077
   330
alpar@1234
   331
    void augment(Node x, typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   332
		 UFE& blossom, UFE& tree);
jacint@1077
   333
jacint@1077
   334
  };
jacint@1077
   335
jacint@1077
   336
jacint@1077
   337
  // **********************************************************************
jacint@1077
   338
  //  IMPLEMENTATIONS
jacint@1077
   339
  // **********************************************************************
jacint@1077
   340
jacint@1077
   341
jacint@1077
   342
  template <typename Graph>
jacint@1077
   343
  void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   344
				      UFE& blossom, UFE& tree) {
jacint@1077
   345
jacint@1077
   346
    std::queue<Node> Q;   //queue of the totally unscanned nodes
jacint@1077
   347
    Q.push(v);  
jacint@1077
   348
    std::queue<Node> R;   
jacint@1077
   349
    //queue of the nodes which must be scanned for a possible shrink
jacint@1077
   350
      
jacint@1077
   351
    while ( !Q.empty() ) {
jacint@1077
   352
      Node x=Q.front();
jacint@1077
   353
      Q.pop();
jacint@1077
   354
      if ( noShrinkStep( x, ear, blossom, tree, Q ) ) return;
jacint@1077
   355
      else R.push(x);
jacint@1077
   356
    }
jacint@1077
   357
      
jacint@1077
   358
    while ( !R.empty() ) {
jacint@1077
   359
      Node x=R.front();
jacint@1077
   360
      R.pop();
jacint@1077
   361
	
jacint@1077
   362
      for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
klao@1158
   363
	Node y=g.runningNode(e);
jacint@1077
   364
jacint@1077
   365
	if ( position[y] == D && blossom.find(x) != blossom.find(y) ) { 
jacint@1077
   366
	  //x and y must be in the same tree
jacint@1077
   367
	
jacint@1077
   368
	  typename Graph::template NodeMap<bool> path(g,false);
jacint@1077
   369
jacint@1077
   370
	  Node b=blossom.find(x);
jacint@1077
   371
	  path.set(b,true);
jacint@1093
   372
	  b=_mate[b];
jacint@1077
   373
	  while ( b!=INVALID ) { 
jacint@1077
   374
	    b=blossom.find(ear[b]);
jacint@1077
   375
	    path.set(b,true);
jacint@1093
   376
	    b=_mate[b];
jacint@1077
   377
	  } //going till the root
jacint@1077
   378
	
jacint@1077
   379
	  Node top=y;
jacint@1077
   380
	  Node middle=blossom.find(top);
jacint@1077
   381
	  Node bottom=x;
jacint@1077
   382
	  while ( !path[middle] )
jacint@1077
   383
	    shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
jacint@1077
   384
		  
jacint@1077
   385
	  Node base=middle;
jacint@1077
   386
	  top=x;
jacint@1077
   387
	  middle=blossom.find(top);
jacint@1077
   388
	  bottom=y;
jacint@1077
   389
	  Node blossom_base=blossom.find(base);
jacint@1077
   390
	  while ( middle!=blossom_base )
jacint@1077
   391
	    shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
jacint@1077
   392
		  
jacint@1077
   393
	  blossom.makeRep(base);
jacint@1077
   394
	} // if shrink is needed
jacint@1077
   395
jacint@1077
   396
	while ( !Q.empty() ) {
jacint@1077
   397
	  Node x=Q.front();
jacint@1077
   398
	  Q.pop();
jacint@1077
   399
	  if ( noShrinkStep(x, ear, blossom, tree, Q) ) return;
jacint@1077
   400
	  else 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@1077
   412
    std::queue<Node> Q;   //queue of the unscanned nodes
jacint@1077
   413
    Q.push(v);  
jacint@1077
   414
    while ( !Q.empty() ) {
jacint@1077
   415
jacint@1077
   416
      Node x=Q.front();
jacint@1077
   417
      Q.pop();
jacint@1077
   418
	
jacint@1077
   419
      for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
klao@1158
   420
	Node y=g.runningNode(e);
jacint@1077
   421
	      
jacint@1077
   422
	switch ( position[y] ) {
jacint@1077
   423
	case D:          //x and y must be in the same tree
jacint@1077
   424
jacint@1077
   425
	  if ( blossom.find(x) != blossom.find(y) ) { //shrink
jacint@1077
   426
	    typename Graph::template NodeMap<bool> path(g,false);
jacint@1077
   427
	      
jacint@1077
   428
	    Node b=blossom.find(x);
jacint@1077
   429
	    path.set(b,true);
jacint@1093
   430
	    b=_mate[b];
jacint@1077
   431
	    while ( b!=INVALID ) { 
jacint@1077
   432
	      b=blossom.find(ear[b]);
jacint@1077
   433
	      path.set(b,true);
jacint@1093
   434
	      b=_mate[b];
jacint@1077
   435
	    } //going till the root
jacint@1077
   436
	
jacint@1077
   437
	    Node top=y;
jacint@1077
   438
	    Node middle=blossom.find(top);
jacint@1077
   439
	    Node bottom=x;
jacint@1077
   440
	    while ( !path[middle] )
jacint@1077
   441
	      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
jacint@1077
   442
		
jacint@1077
   443
	    Node base=middle;
jacint@1077
   444
	    top=x;
jacint@1077
   445
	    middle=blossom.find(top);
jacint@1077
   446
	    bottom=y;
jacint@1077
   447
	    Node blossom_base=blossom.find(base);
jacint@1077
   448
	    while ( middle!=blossom_base )
jacint@1077
   449
	      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
jacint@1077
   450
		
jacint@1077
   451
	    blossom.makeRep(base);
jacint@1077
   452
	  }
jacint@1077
   453
	  break;
jacint@1077
   454
	case C:
jacint@1093
   455
	  if ( _mate[y]!=INVALID ) {   //grow
jacint@1077
   456
jacint@1077
   457
	    ear.set(y,x);
jacint@1093
   458
	    Node w=_mate[y];
jacint@1077
   459
	    blossom.insert(w);
jacint@1077
   460
	    position.set(y,A); 
jacint@1077
   461
	    position.set(w,D); 
jacint@1077
   462
	    tree.insert(y);
jacint@1077
   463
	    tree.insert(w);
jacint@1077
   464
	    tree.join(y,blossom.find(x));  
jacint@1077
   465
	    tree.join(w,y);  
jacint@1077
   466
	    Q.push(w);
jacint@1077
   467
	  } else {                 //augment  
jacint@1077
   468
	    augment(x, ear, blossom, tree);
jacint@1093
   469
	    _mate.set(x,y);
jacint@1093
   470
	    _mate.set(y,x);
jacint@1077
   471
	    return;
jacint@1077
   472
	  } //if 
jacint@1077
   473
	  break;
jacint@1077
   474
	default: break;
jacint@1077
   475
	}
jacint@1077
   476
      }
jacint@1077
   477
    }
jacint@1077
   478
  }
jacint@1077
   479
jacint@1077
   480
  template <typename Graph>
alpar@1234
   481
  bool MaxMatching<Graph>::noShrinkStep(Node x,
alpar@1234
   482
					typename Graph::template 
alpar@1234
   483
					NodeMap<Node>& ear,  
alpar@1234
   484
					UFE& blossom, UFE& tree,
alpar@1234
   485
					std::queue<Node>& Q) {
jacint@1077
   486
    for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
klao@1158
   487
      Node y=g.runningNode(e);
jacint@1077
   488
	
jacint@1077
   489
      if ( position[y]==C ) {
jacint@1093
   490
	if ( _mate[y]!=INVALID ) {       //grow
jacint@1077
   491
	  ear.set(y,x);
jacint@1093
   492
	  Node w=_mate[y];
jacint@1077
   493
	  blossom.insert(w);
jacint@1077
   494
	  position.set(y,A);
jacint@1077
   495
	  position.set(w,D);
jacint@1077
   496
	  tree.insert(y);
jacint@1077
   497
	  tree.insert(w);
jacint@1077
   498
	  tree.join(y,blossom.find(x));  
jacint@1077
   499
	  tree.join(w,y);  
jacint@1077
   500
	  Q.push(w);
jacint@1077
   501
	} else {                      //augment 
jacint@1077
   502
	  augment(x, ear, blossom, tree);
jacint@1093
   503
	  _mate.set(x,y);
jacint@1093
   504
	  _mate.set(y,x);
jacint@1077
   505
	  return true;
jacint@1077
   506
	}
jacint@1077
   507
      }
jacint@1077
   508
    }
jacint@1077
   509
    return false;
jacint@1077
   510
  }
jacint@1077
   511
jacint@1077
   512
  template <typename Graph>
alpar@1234
   513
  void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom,
alpar@1234
   514
				      typename Graph::template
alpar@1234
   515
				      NodeMap<Node>& ear,  
alpar@1234
   516
				      UFE& blossom, UFE& tree,
alpar@1234
   517
				      std::queue<Node>& Q) {
jacint@1077
   518
    ear.set(top,bottom);
jacint@1077
   519
    Node t=top;
jacint@1077
   520
    while ( t!=middle ) {
jacint@1093
   521
      Node u=_mate[t];
jacint@1077
   522
      t=ear[u];
jacint@1077
   523
      ear.set(t,u);
jacint@1077
   524
    } 
jacint@1093
   525
    bottom=_mate[middle];
jacint@1077
   526
    position.set(bottom,D);
jacint@1077
   527
    Q.push(bottom);
jacint@1077
   528
    top=ear[bottom];		
jacint@1077
   529
    Node oldmiddle=middle;
jacint@1077
   530
    middle=blossom.find(top);
jacint@1077
   531
    tree.erase(bottom);
jacint@1077
   532
    tree.erase(oldmiddle);
jacint@1077
   533
    blossom.insert(bottom);
jacint@1077
   534
    blossom.join(bottom, oldmiddle);
jacint@1077
   535
    blossom.join(top, oldmiddle);
jacint@1077
   536
  }
jacint@1077
   537
jacint@1077
   538
  template <typename Graph>
alpar@1234
   539
  void MaxMatching<Graph>::augment(Node x,
alpar@1234
   540
				   typename Graph::template NodeMap<Node>& ear,  
jacint@1077
   541
				   UFE& blossom, UFE& tree) { 
jacint@1093
   542
    Node v=_mate[x];
jacint@1077
   543
    while ( v!=INVALID ) {
jacint@1077
   544
	
jacint@1077
   545
      Node u=ear[v];
jacint@1093
   546
      _mate.set(v,u);
jacint@1077
   547
      Node tmp=v;
jacint@1093
   548
      v=_mate[u];
jacint@1093
   549
      _mate.set(u,tmp);
jacint@1077
   550
    }
jacint@1077
   551
    typename UFE::ItemIt it;
jacint@1077
   552
    for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) {   
jacint@1077
   553
      if ( position[it] == D ) {
jacint@1077
   554
	typename UFE::ItemIt b_it;
jacint@1077
   555
	for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) {  
jacint@1077
   556
	  position.set( b_it ,C);
jacint@1077
   557
	}
jacint@1077
   558
	blossom.eraseClass(it);
jacint@1077
   559
      } else position.set( it ,C);
jacint@1077
   560
    }
jacint@1077
   561
    tree.eraseClass(x);
jacint@1077
   562
jacint@1077
   563
  }
jacint@1077
   564
jacint@1077
   565
  /// @}
jacint@1077
   566
  
jacint@1077
   567
} //END OF NAMESPACE LEMON
jacint@1077
   568
jacint@1165
   569
#endif //LEMON_MAX_MATCHING_H