lemon/max_matching.h
changeset 2026 8d49961ec50f
parent 1993 2115143eceea
child 2042 bdc953f2a449
equal deleted inserted replaced
5:98c4d3006431 6:38ce1bdee72d
   112     ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs
   112     ///If heur=0 it runs Edmonds' algorithm. If heur=1 it runs
   113     ///Edmonds' algorithm with a heuristic of postponing shrinks,
   113     ///Edmonds' algorithm with a heuristic of postponing shrinks,
   114     ///giving a faster algorithm for dense graphs.  
   114     ///giving a faster algorithm for dense graphs.  
   115     void runEdmonds( int heur = 1 ) {
   115     void runEdmonds( int heur = 1 ) {
   116       
   116       
       
   117       //each vertex is put to C
   117       for(NodeIt v(g); v!=INVALID; ++v)
   118       for(NodeIt v(g); v!=INVALID; ++v)
   118 	position.set(v,C);      
   119 	position.set(v,C);      
   119       
   120       
   120       typename Graph::template NodeMap<Node> ear(g,INVALID); 
   121       typename Graph::template NodeMap<Node> ear(g,INVALID); 
   121       //undefined for the base nodes of the blossoms (i.e. for the
   122       //undefined for the base nodes of the blossoms (i.e. for the
   126       typename UFE::MapType tree_base(g);
   127       typename UFE::MapType tree_base(g);
   127       UFE tree(tree_base);
   128       UFE tree(tree_base);
   128       //If these UFE's would be members of the class then also
   129       //If these UFE's would be members of the class then also
   129       //blossom_base and tree_base should be a member.
   130       //blossom_base and tree_base should be a member.
   130       
   131       
       
   132       //We build only one tree and the other vertices uncovered by the
       
   133       //matching belong to C. (They can be considered as singleton
       
   134       //trees.) If this tree can be augmented or no more
       
   135       //grow/augmentation/shrink is possible then we return to this
       
   136       //"for" cycle.
   131       for(NodeIt v(g); v!=INVALID; ++v) {
   137       for(NodeIt v(g); v!=INVALID; ++v) {
   132 	if ( position[v]==C && _mate[v]==INVALID ) {
   138 	if ( position[v]==C && _mate[v]==INVALID ) {
   133 	  blossom.insert(v);
   139 	  blossom.insert(v);
   134 	  tree.insert(v); 
   140 	  tree.insert(v); 
   135 	  position.set(v,D);
   141 	  position.set(v,D);
   221     ///have the property that if \c g.oppositeNode(u,map[u])==v then
   227     ///have the property that if \c g.oppositeNode(u,map[u])==v then
   222     ///\c \c g.oppositeNode(v,map[v])==u holds, and now some edge
   228     ///\c \c g.oppositeNode(v,map[v])==u holds, and now some edge
   223     ///joining \c u to \c v will be an edge of the matching.
   229     ///joining \c u to \c v will be an edge of the matching.
   224     template<typename NMapE>
   230     template<typename NMapE>
   225     void readNMapEdge(NMapE& map) {
   231     void readNMapEdge(NMapE& map) {
   226      for(NodeIt v(g); v!=INVALID; ++v) {
   232       for(NodeIt v(g); v!=INVALID; ++v) {
   227        UEdge e=map[v];
   233 	UEdge e=map[v];
   228 	if ( e!=INVALID )
   234 	if ( e!=INVALID )
   229 	  _mate.set(v,g.oppositeNode(v,e));
   235 	  _mate.set(v,g.oppositeNode(v,e));
   230       } 
   236       } 
   231     } 
   237     } 
   232     
   238     
   321 		    UFE& blossom, UFE& tree);
   327 		    UFE& blossom, UFE& tree);
   322 
   328 
   323     void normShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
   329     void normShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
   324 		    UFE& blossom, UFE& tree);
   330 		    UFE& blossom, UFE& tree);
   325 
   331 
   326     bool noShrinkStep(Node x, typename Graph::template NodeMap<Node>& ear,  
   332     void shrink(Node x,Node y, typename Graph::template NodeMap<Node>& ear,  
   327 		      UFE& blossom, UFE& tree, std::queue<Node>& Q);
   333 		UFE& blossom, UFE& tree,std::queue<Node>& Q);
   328 
   334 
   329     void shrinkStep(Node& top, Node& middle, Node& bottom,
   335     void shrinkStep(Node& top, Node& middle, Node& bottom,
   330 		    typename Graph::template NodeMap<Node>& ear,  
   336 		    typename Graph::template NodeMap<Node>& ear,  
   331 		    UFE& blossom, UFE& tree, std::queue<Node>& Q);
   337 		    UFE& blossom, UFE& tree, std::queue<Node>& Q);
   332 
   338 
       
   339     bool growOrAugment(Node& y, Node& x, typename Graph::template 
       
   340 		       NodeMap<Node>& ear, UFE& blossom, UFE& tree, 
       
   341 		       std::queue<Node>& Q);
       
   342 
   333     void augment(Node x, typename Graph::template NodeMap<Node>& ear,  
   343     void augment(Node x, typename Graph::template NodeMap<Node>& ear,  
   334 		 UFE& blossom, UFE& tree);
   344 		 UFE& blossom, UFE& tree);
   335 
   345 
   336   };
   346   };
   337 
   347 
   340   //  IMPLEMENTATIONS
   350   //  IMPLEMENTATIONS
   341   // **********************************************************************
   351   // **********************************************************************
   342 
   352 
   343 
   353 
   344   template <typename Graph>
   354   template <typename Graph>
   345   void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,  
   355   void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template 
   346 				      UFE& blossom, UFE& tree) {
   356 				      NodeMap<Node>& ear, UFE& blossom, UFE& tree) {
       
   357     //We have one tree which we grow, and also shrink but only if it cannot be
       
   358     //postponed. If we augment then we return to the "for" cycle of
       
   359     //runEdmonds().
   347 
   360 
   348     std::queue<Node> Q;   //queue of the totally unscanned nodes
   361     std::queue<Node> Q;   //queue of the totally unscanned nodes
   349     Q.push(v);  
   362     Q.push(v);  
   350     std::queue<Node> R;   
   363     std::queue<Node> R;   
   351     //queue of the nodes which must be scanned for a possible shrink
   364     //queue of the nodes which must be scanned for a possible shrink
   352       
   365       
   353     while ( !Q.empty() ) {
   366     while ( !Q.empty() ) {
   354       Node x=Q.front();
   367       Node x=Q.front();
   355       Q.pop();
   368       Q.pop();
   356       if ( noShrinkStep( x, ear, blossom, tree, Q ) ) return;
   369       for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
   357       else R.push(x);
   370 	Node y=g.runningNode(e);
       
   371 	//growOrAugment grows if y is covered by the matching and
       
   372 	//augments if not. In this latter case it returns 1.
       
   373 	if ( position[y]==C && growOrAugment(y, x, ear, blossom, tree, Q) ) return;
       
   374       }
       
   375       R.push(x);
   358     }
   376     }
   359       
   377       
   360     while ( !R.empty() ) {
   378     while ( !R.empty() ) {
   361       Node x=R.front();
   379       Node x=R.front();
   362       R.pop();
   380       R.pop();
   363 	
   381 	
   364       for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
   382       for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
   365 	Node y=g.runningNode(e);
   383 	Node y=g.runningNode(e);
   366 
   384 
   367 	if ( position[y] == D && blossom.find(x) != blossom.find(y) ) { 
   385 	if ( position[y] == D && blossom.find(x) != blossom.find(y) )  
   368 	  //x and y must be in the same tree
   386 	  //Recall that we have only one tree.
       
   387 	  shrink( x, y, ear, blossom, tree, Q);	
   369 	
   388 	
   370 	  typename Graph::template NodeMap<bool> path(g,false);
       
   371 
       
   372 	  Node b=blossom.find(x);
       
   373 	  path.set(b,true);
       
   374 	  b=_mate[b];
       
   375 	  while ( b!=INVALID ) { 
       
   376 	    b=blossom.find(ear[b]);
       
   377 	    path.set(b,true);
       
   378 	    b=_mate[b];
       
   379 	  } //going till the root
       
   380 	
       
   381 	  Node top=y;
       
   382 	  Node middle=blossom.find(top);
       
   383 	  Node bottom=x;
       
   384 	  while ( !path[middle] )
       
   385 	    shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
       
   386 		  
       
   387 	  Node base=middle;
       
   388 	  top=x;
       
   389 	  middle=blossom.find(top);
       
   390 	  bottom=y;
       
   391 	  Node blossom_base=blossom.find(base);
       
   392 	  while ( middle!=blossom_base )
       
   393 	    shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
       
   394 		  
       
   395 	  blossom.makeRep(base);
       
   396 	} // if shrink is needed
       
   397 
       
   398 	while ( !Q.empty() ) {
   389 	while ( !Q.empty() ) {
   399 	  Node x=Q.front();
   390 	  Node x=Q.front();
   400 	  Q.pop();
   391 	  Q.pop();
   401 	  if ( noShrinkStep(x, ear, blossom, tree, Q) ) return;
   392 	  for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
   402 	  else R.push(x);
   393 	    Node y=g.runningNode(e);
       
   394 	    //growOrAugment grows if y is covered by the matching and
       
   395 	    //augments if not. In this latter case it returns 1.
       
   396 	    if ( position[y]==C && growOrAugment(y, x, ear, blossom, tree, Q) ) return;
       
   397 	  }
       
   398 	  R.push(x);
   403 	}
   399 	}
   404       } //for e
   400       } //for e
   405     } // while ( !R.empty() )
   401     } // while ( !R.empty() )
   406   }
   402   }
   407 
   403 
   409   template <typename Graph>
   405   template <typename Graph>
   410   void MaxMatching<Graph>::normShrink(Node v,
   406   void MaxMatching<Graph>::normShrink(Node v,
   411 				      typename Graph::template
   407 				      typename Graph::template
   412 				      NodeMap<Node>& ear,  
   408 				      NodeMap<Node>& ear,  
   413 				      UFE& blossom, UFE& tree) {
   409 				      UFE& blossom, UFE& tree) {
       
   410     //We have one tree, which we grow and shrink. If we augment then we
       
   411     //return to the "for" cycle of runEdmonds().
       
   412     
   414     std::queue<Node> Q;   //queue of the unscanned nodes
   413     std::queue<Node> Q;   //queue of the unscanned nodes
   415     Q.push(v);  
   414     Q.push(v);  
   416     while ( !Q.empty() ) {
   415     while ( !Q.empty() ) {
   417 
   416 
   418       Node x=Q.front();
   417       Node x=Q.front();
   421       for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
   420       for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
   422 	Node y=g.runningNode(e);
   421 	Node y=g.runningNode(e);
   423 	      
   422 	      
   424 	switch ( position[y] ) {
   423 	switch ( position[y] ) {
   425 	case D:          //x and y must be in the same tree
   424 	case D:          //x and y must be in the same tree
   426 
   425 	  if ( blossom.find(x) != blossom.find(y) )
   427 	  if ( blossom.find(x) != blossom.find(y) ) { //shrink
   426 	    //x and y are in the same tree
   428 	    typename Graph::template NodeMap<bool> path(g,false);
   427 	    shrink( x, y, ear, blossom, tree, Q);
   429 	      
       
   430 	    Node b=blossom.find(x);
       
   431 	    path.set(b,true);
       
   432 	    b=_mate[b];
       
   433 	    while ( b!=INVALID ) { 
       
   434 	      b=blossom.find(ear[b]);
       
   435 	      path.set(b,true);
       
   436 	      b=_mate[b];
       
   437 	    } //going till the root
       
   438 	
       
   439 	    Node top=y;
       
   440 	    Node middle=blossom.find(top);
       
   441 	    Node bottom=x;
       
   442 	    while ( !path[middle] )
       
   443 	      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
       
   444 		
       
   445 	    Node base=middle;
       
   446 	    top=x;
       
   447 	    middle=blossom.find(top);
       
   448 	    bottom=y;
       
   449 	    Node blossom_base=blossom.find(base);
       
   450 	    while ( middle!=blossom_base )
       
   451 	      shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
       
   452 		
       
   453 	    blossom.makeRep(base);
       
   454 	  }
       
   455 	  break;
   428 	  break;
   456 	case C:
   429 	case C:
   457 	  if ( _mate[y]!=INVALID ) {   //grow
   430 	  //growOrAugment grows if y is covered by the matching and
   458 
   431 	  //augments if not. In this latter case it returns 1.
   459 	    ear.set(y,x);
   432 	  if ( growOrAugment(y, x, ear, blossom, tree, Q) ) return;
   460 	    Node w=_mate[y];
       
   461 	    blossom.insert(w);
       
   462 	    position.set(y,A); 
       
   463 	    position.set(w,D); 
       
   464 	    tree.insert(y);
       
   465 	    tree.insert(w);
       
   466 	    tree.join(y,blossom.find(x));  
       
   467 	    tree.join(w,y);  
       
   468 	    Q.push(w);
       
   469 	  } else {                 //augment  
       
   470 	    augment(x, ear, blossom, tree);
       
   471 	    _mate.set(x,y);
       
   472 	    _mate.set(y,x);
       
   473 	    return;
       
   474 	  } //if 
       
   475 	  break;
   433 	  break;
   476 	default: break;
   434 	default: break;
   477 	}
   435        	}
   478       }
   436       }
   479     }
   437     }
   480   }
   438   }
   481 
   439   
   482   template <typename Graph>
   440 
   483   bool MaxMatching<Graph>::noShrinkStep(Node x,
   441   template <typename Graph>
   484 					typename Graph::template 
   442     void MaxMatching<Graph>::shrink(Node x,Node y, typename 
   485 					NodeMap<Node>& ear,  
   443 				    Graph::template NodeMap<Node>& ear,  
   486 					UFE& blossom, UFE& tree,
   444 				    UFE& blossom, UFE& tree, std::queue<Node>& Q) {
   487 					std::queue<Node>& Q) {
   445     //x and y are the two adjacent vertices in two blossoms.
   488     for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
   446    
   489       Node y=g.runningNode(e);
   447     typename Graph::template NodeMap<bool> path(g,false);
   490 	
   448     
   491       if ( position[y]==C ) {
   449     Node b=blossom.find(x);
   492 	if ( _mate[y]!=INVALID ) {       //grow
   450     path.set(b,true);
   493 	  ear.set(y,x);
   451     b=_mate[b];
   494 	  Node w=_mate[y];
   452     while ( b!=INVALID ) { 
   495 	  blossom.insert(w);
   453       b=blossom.find(ear[b]);
   496 	  position.set(y,A);
   454       path.set(b,true);
   497 	  position.set(w,D);
   455       b=_mate[b];
   498 	  tree.insert(y);
   456     } //we go until the root through bases of blossoms and odd vertices
   499 	  tree.insert(w);
   457     
   500 	  tree.join(y,blossom.find(x));  
   458     Node top=y;
   501 	  tree.join(w,y);  
   459     Node middle=blossom.find(top);
   502 	  Q.push(w);
   460     Node bottom=x;
   503 	} else {                      //augment 
   461     while ( !path[middle] )
   504 	  augment(x, ear, blossom, tree);
   462       shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
   505 	  _mate.set(x,y);
   463     //Until we arrive to a node on the path, we update blossom, tree
   506 	  _mate.set(y,x);
   464     //and the positions of the odd nodes.
   507 	  return true;
   465     
   508 	}
   466     Node base=middle;
   509       }
   467     top=x;
   510     }
   468     middle=blossom.find(top);
   511     return false;
   469     bottom=y;
       
   470     Node blossom_base=blossom.find(base);
       
   471     while ( middle!=blossom_base )
       
   472       shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
       
   473     //Until we arrive to a node on the path, we update blossom, tree
       
   474     //and the positions of the odd nodes.
       
   475     
       
   476     blossom.makeRep(base);
   512   }
   477   }
       
   478 
       
   479 
   513 
   480 
   514   template <typename Graph>
   481   template <typename Graph>
   515   void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom,
   482   void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom,
   516 				      typename Graph::template
   483 				      typename Graph::template
   517 				      NodeMap<Node>& ear,  
   484 				      NodeMap<Node>& ear,  
   518 				      UFE& blossom, UFE& tree,
   485 				      UFE& blossom, UFE& tree,
   519 				      std::queue<Node>& Q) {
   486 				      std::queue<Node>& Q) {
       
   487     //We traverse a blossom and update everything.
       
   488     
   520     ear.set(top,bottom);
   489     ear.set(top,bottom);
   521     Node t=top;
   490     Node t=top;
   522     while ( t!=middle ) {
   491     while ( t!=middle ) {
   523       Node u=_mate[t];
   492       Node u=_mate[t];
   524       t=ear[u];
   493       t=ear[u];
   535     blossom.insert(bottom);
   504     blossom.insert(bottom);
   536     blossom.join(bottom, oldmiddle);
   505     blossom.join(bottom, oldmiddle);
   537     blossom.join(top, oldmiddle);
   506     blossom.join(top, oldmiddle);
   538   }
   507   }
   539 
   508 
       
   509 
       
   510   template <typename Graph>
       
   511   bool MaxMatching<Graph>::growOrAugment(Node& y, Node& x, typename Graph::template
       
   512 					 NodeMap<Node>& ear, UFE& blossom, UFE& tree,
       
   513 					 std::queue<Node>& Q) {
       
   514     //x is in a blossom in the tree, y is outside. If y is covered by
       
   515     //the matching we grow, otherwise we augment. In this case we
       
   516     //return 1.
       
   517     
       
   518     if ( _mate[y]!=INVALID ) {       //grow
       
   519       ear.set(y,x);
       
   520       Node w=_mate[y];
       
   521       blossom.insert(w);
       
   522       position.set(y,A);
       
   523       position.set(w,D);
       
   524       tree.insert(y);
       
   525       tree.insert(w);
       
   526       tree.join(y,blossom.find(x));  
       
   527       tree.join(w,y);  
       
   528       Q.push(w);
       
   529     } else {                      //augment 
       
   530       augment(x, ear, blossom, tree);
       
   531       _mate.set(x,y);
       
   532       _mate.set(y,x);
       
   533       return true;
       
   534     }
       
   535     return false;
       
   536   }
       
   537   
       
   538 
   540   template <typename Graph>
   539   template <typename Graph>
   541   void MaxMatching<Graph>::augment(Node x,
   540   void MaxMatching<Graph>::augment(Node x,
   542 				   typename Graph::template NodeMap<Node>& ear,  
   541 				   typename Graph::template NodeMap<Node>& ear,  
   543 				   UFE& blossom, UFE& tree) { 
   542 				   UFE& blossom, UFE& tree) { 
   544     Node v=_mate[x];
   543     Node v=_mate[x];
   548       _mate.set(v,u);
   547       _mate.set(v,u);
   549       Node tmp=v;
   548       Node tmp=v;
   550       v=_mate[u];
   549       v=_mate[u];
   551       _mate.set(u,tmp);
   550       _mate.set(u,tmp);
   552     }
   551     }
       
   552     Node y=blossom.find(x);
   553     typename UFE::ItemIt it;
   553     typename UFE::ItemIt it;
   554     for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) {   
   554     for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) {   
   555       if ( position[it] == D ) {
   555       if ( position[it] == D ) {
   556 	typename UFE::ItemIt b_it;
   556 	typename UFE::ItemIt b_it;
   557 	for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) {  
   557 	for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) {  
   558 	  position.set( b_it ,C);
   558 	  position.set( b_it ,C);
   559 	}
   559 	}
   560 	blossom.eraseClass(it);
   560 	blossom.eraseClass(it);
   561       } else position.set( it ,C);
   561       } else position.set( it ,C);
   562     }
   562     }
   563     tree.eraseClass(x);
   563     tree.eraseClass(y);
   564 
   564 
   565   }
   565   }
   566 
   566 
   567   /// @}
   567   /// @}
   568   
   568