src/work/jacint/max_matching.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000 (2004-09-08)
changeset 822 88226d9fe821
parent 586 04fdffd38e89
child 921 818510fa3d99
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

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