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