lemon/max_matching.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2042 bdc953f2a449
child 2308 cddae1c4fee6
permissions -rwxr-xr-x
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
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