00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef LEMON_MAX_MATCHING_H
00018 #define LEMON_MAX_MATCHING_H
00019
00020 #include <queue>
00021 #include <lemon/invalid.h>
00022 #include <lemon/unionfind.h>
00023 #include <lemon/graph_utils.h>
00024
00028
00029 namespace lemon {
00030
00033
00035
00055 template <typename Graph>
00056 class MaxMatching {
00057
00058 protected:
00059
00060 typedef typename Graph::Node Node;
00061 typedef typename Graph::Edge Edge;
00062 typedef typename Graph::UndirEdge UndirEdge;
00063 typedef typename Graph::UndirEdgeIt UndirEdgeIt;
00064 typedef typename Graph::NodeIt NodeIt;
00065 typedef typename Graph::IncEdgeIt IncEdgeIt;
00066
00067 typedef UnionFindEnum<Node, Graph::template NodeMap> UFE;
00068
00069 public:
00070
00072
00078 enum pos_enum {
00079 D=0,
00080 A=1,
00081 C=2
00082 };
00083
00084 protected:
00085
00086 static const int HEUR_density=2;
00087 const Graph& g;
00088 typename Graph::template NodeMap<Node> _mate;
00089 typename Graph::template NodeMap<pos_enum> position;
00090
00091 public:
00092
00093 MaxMatching(const Graph& _g) : g(_g), _mate(_g,INVALID), position(_g) {}
00094
00096
00100 void run() {
00101 if ( countUndirEdges(g) < HEUR_density*countNodes(g) ) {
00102 greedyMatching();
00103 runEdmonds(0);
00104 } else runEdmonds(1);
00105 }
00106
00107
00109
00113 void runEdmonds( int heur = 1 ) {
00114
00115 for(NodeIt v(g); v!=INVALID; ++v)
00116 position.set(v,C);
00117
00118 typename Graph::template NodeMap<Node> ear(g,INVALID);
00119
00120
00121
00122 typename UFE::MapType blossom_base(g);
00123 UFE blossom(blossom_base);
00124 typename UFE::MapType tree_base(g);
00125 UFE tree(tree_base);
00126
00127
00128
00129 for(NodeIt v(g); v!=INVALID; ++v) {
00130 if ( position[v]==C && _mate[v]==INVALID ) {
00131 blossom.insert(v);
00132 tree.insert(v);
00133 position.set(v,D);
00134 if ( heur == 1 ) lateShrink( v, ear, blossom, tree );
00135 else normShrink( v, ear, blossom, tree );
00136 }
00137 }
00138 }
00139
00140
00142
00145 void greedyMatching() {
00146 for(NodeIt v(g); v!=INVALID; ++v)
00147 if ( _mate[v]==INVALID ) {
00148 for( IncEdgeIt e(g,v); e!=INVALID ; ++e ) {
00149 Node y=g.runningNode(e);
00150 if ( _mate[y]==INVALID && y!=v ) {
00151 _mate.set(v,y);
00152 _mate.set(y,v);
00153 break;
00154 }
00155 }
00156 }
00157 }
00158
00160
00163 int size() const {
00164 int s=0;
00165 for(NodeIt v(g); v!=INVALID; ++v) {
00166 if ( _mate[v]!=INVALID ) {
00167 ++s;
00168 }
00169 }
00170 return s/2;
00171 }
00172
00173
00175
00178 void resetMatching() {
00179 for(NodeIt v(g); v!=INVALID; ++v)
00180 _mate.set(v,INVALID);
00181 }
00182
00184
00187 Node mate(Node& node) const {
00188 return _mate[node];
00189 }
00190
00192
00196 template<typename NMapN>
00197 void readNMapNode(NMapN& map) {
00198 for(NodeIt v(g); v!=INVALID; ++v) {
00199 _mate.set(v,map[v]);
00200 }
00201 }
00202
00204
00208 template<typename NMapN>
00209 void writeNMapNode (NMapN& map) const {
00210 for(NodeIt v(g); v!=INVALID; ++v) {
00211 map.set(v,_mate[v]);
00212 }
00213 }
00214
00216
00222 template<typename NMapE>
00223 void readNMapEdge(NMapE& map) {
00224 for(NodeIt v(g); v!=INVALID; ++v) {
00225 UndirEdge e=map[v];
00226 if ( e!=INVALID )
00227 _mate.set(v,g.oppositeNode(v,e));
00228 }
00229 }
00230
00232
00238 template<typename NMapE>
00239 void writeNMapEdge (NMapE& map) const {
00240 typename Graph::template NodeMap<bool> todo(g,true);
00241 for(NodeIt v(g); v!=INVALID; ++v) {
00242 if ( todo[v] && _mate[v]!=INVALID ) {
00243 Node u=_mate[v];
00244 for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
00245 if ( g.runningNode(e) == u ) {
00246 map.set(u,e);
00247 map.set(v,e);
00248 todo.set(u,false);
00249 todo.set(v,false);
00250 break;
00251 }
00252 }
00253 }
00254 }
00255 }
00256
00257
00259
00264 template<typename EMapB>
00265 void readEMapBool(EMapB& map) {
00266 for(UndirEdgeIt e(g); e!=INVALID; ++e) {
00267 if ( map[e] ) {
00268 Node u=g.source(e);
00269 Node v=g.target(e);
00270 _mate.set(u,v);
00271 _mate.set(v,u);
00272 }
00273 }
00274 }
00275
00276
00278
00283 template<typename EMapB>
00284 void writeEMapBool (EMapB& map) const {
00285 for(UndirEdgeIt e(g); e!=INVALID; ++e) map.set(e,false);
00286
00287 typename Graph::template NodeMap<bool> todo(g,true);
00288 for(NodeIt v(g); v!=INVALID; ++v) {
00289 if ( todo[v] && _mate[v]!=INVALID ) {
00290 Node u=_mate[v];
00291 for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
00292 if ( g.runningNode(e) == u ) {
00293 map.set(e,true);
00294 todo.set(u,false);
00295 todo.set(v,false);
00296 break;
00297 }
00298 }
00299 }
00300 }
00301 }
00302
00303
00306
00310 template<typename NMapEnum>
00311 void writePos (NMapEnum& map) const {
00312 for(NodeIt v(g); v!=INVALID; ++v) map.set(v,position[v]);
00313 }
00314
00315 private:
00316
00317
00318 void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,
00319 UFE& blossom, UFE& tree);
00320
00321 void normShrink(Node v, typename Graph::template NodeMap<Node>& ear,
00322 UFE& blossom, UFE& tree);
00323
00324 bool noShrinkStep(Node x, typename Graph::template NodeMap<Node>& ear,
00325 UFE& blossom, UFE& tree, std::queue<Node>& Q);
00326
00327 void shrinkStep(Node& top, Node& middle, Node& bottom,
00328 typename Graph::template NodeMap<Node>& ear,
00329 UFE& blossom, UFE& tree, std::queue<Node>& Q);
00330
00331 void augment(Node x, typename Graph::template NodeMap<Node>& ear,
00332 UFE& blossom, UFE& tree);
00333
00334 };
00335
00336
00337
00338
00339
00340
00341
00342 template <typename Graph>
00343 void MaxMatching<Graph>::lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,
00344 UFE& blossom, UFE& tree) {
00345
00346 std::queue<Node> Q;
00347 Q.push(v);
00348 std::queue<Node> R;
00349
00350
00351 while ( !Q.empty() ) {
00352 Node x=Q.front();
00353 Q.pop();
00354 if ( noShrinkStep( x, ear, blossom, tree, Q ) ) return;
00355 else R.push(x);
00356 }
00357
00358 while ( !R.empty() ) {
00359 Node x=R.front();
00360 R.pop();
00361
00362 for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
00363 Node y=g.runningNode(e);
00364
00365 if ( position[y] == D && blossom.find(x) != blossom.find(y) ) {
00366
00367
00368 typename Graph::template NodeMap<bool> path(g,false);
00369
00370 Node b=blossom.find(x);
00371 path.set(b,true);
00372 b=_mate[b];
00373 while ( b!=INVALID ) {
00374 b=blossom.find(ear[b]);
00375 path.set(b,true);
00376 b=_mate[b];
00377 }
00378
00379 Node top=y;
00380 Node middle=blossom.find(top);
00381 Node bottom=x;
00382 while ( !path[middle] )
00383 shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
00384
00385 Node base=middle;
00386 top=x;
00387 middle=blossom.find(top);
00388 bottom=y;
00389 Node blossom_base=blossom.find(base);
00390 while ( middle!=blossom_base )
00391 shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
00392
00393 blossom.makeRep(base);
00394 }
00395
00396 while ( !Q.empty() ) {
00397 Node x=Q.front();
00398 Q.pop();
00399 if ( noShrinkStep(x, ear, blossom, tree, Q) ) return;
00400 else R.push(x);
00401 }
00402 }
00403 }
00404 }
00405
00406
00407 template <typename Graph>
00408 void MaxMatching<Graph>::normShrink(Node v,
00409 typename Graph::template
00410 NodeMap<Node>& ear,
00411 UFE& blossom, UFE& tree) {
00412 std::queue<Node> Q;
00413 Q.push(v);
00414 while ( !Q.empty() ) {
00415
00416 Node x=Q.front();
00417 Q.pop();
00418
00419 for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
00420 Node y=g.runningNode(e);
00421
00422 switch ( position[y] ) {
00423 case D:
00424
00425 if ( blossom.find(x) != blossom.find(y) ) {
00426 typename Graph::template NodeMap<bool> path(g,false);
00427
00428 Node b=blossom.find(x);
00429 path.set(b,true);
00430 b=_mate[b];
00431 while ( b!=INVALID ) {
00432 b=blossom.find(ear[b]);
00433 path.set(b,true);
00434 b=_mate[b];
00435 }
00436
00437 Node top=y;
00438 Node middle=blossom.find(top);
00439 Node bottom=x;
00440 while ( !path[middle] )
00441 shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
00442
00443 Node base=middle;
00444 top=x;
00445 middle=blossom.find(top);
00446 bottom=y;
00447 Node blossom_base=blossom.find(base);
00448 while ( middle!=blossom_base )
00449 shrinkStep(top, middle, bottom, ear, blossom, tree, Q);
00450
00451 blossom.makeRep(base);
00452 }
00453 break;
00454 case C:
00455 if ( _mate[y]!=INVALID ) {
00456
00457 ear.set(y,x);
00458 Node w=_mate[y];
00459 blossom.insert(w);
00460 position.set(y,A);
00461 position.set(w,D);
00462 tree.insert(y);
00463 tree.insert(w);
00464 tree.join(y,blossom.find(x));
00465 tree.join(w,y);
00466 Q.push(w);
00467 } else {
00468 augment(x, ear, blossom, tree);
00469 _mate.set(x,y);
00470 _mate.set(y,x);
00471 return;
00472 }
00473 break;
00474 default: break;
00475 }
00476 }
00477 }
00478 }
00479
00480 template <typename Graph>
00481 bool MaxMatching<Graph>::noShrinkStep(Node x,
00482 typename Graph::template
00483 NodeMap<Node>& ear,
00484 UFE& blossom, UFE& tree,
00485 std::queue<Node>& Q) {
00486 for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
00487 Node y=g.runningNode(e);
00488
00489 if ( position[y]==C ) {
00490 if ( _mate[y]!=INVALID ) {
00491 ear.set(y,x);
00492 Node w=_mate[y];
00493 blossom.insert(w);
00494 position.set(y,A);
00495 position.set(w,D);
00496 tree.insert(y);
00497 tree.insert(w);
00498 tree.join(y,blossom.find(x));
00499 tree.join(w,y);
00500 Q.push(w);
00501 } else {
00502 augment(x, ear, blossom, tree);
00503 _mate.set(x,y);
00504 _mate.set(y,x);
00505 return true;
00506 }
00507 }
00508 }
00509 return false;
00510 }
00511
00512 template <typename Graph>
00513 void MaxMatching<Graph>::shrinkStep(Node& top, Node& middle, Node& bottom,
00514 typename Graph::template
00515 NodeMap<Node>& ear,
00516 UFE& blossom, UFE& tree,
00517 std::queue<Node>& Q) {
00518 ear.set(top,bottom);
00519 Node t=top;
00520 while ( t!=middle ) {
00521 Node u=_mate[t];
00522 t=ear[u];
00523 ear.set(t,u);
00524 }
00525 bottom=_mate[middle];
00526 position.set(bottom,D);
00527 Q.push(bottom);
00528 top=ear[bottom];
00529 Node oldmiddle=middle;
00530 middle=blossom.find(top);
00531 tree.erase(bottom);
00532 tree.erase(oldmiddle);
00533 blossom.insert(bottom);
00534 blossom.join(bottom, oldmiddle);
00535 blossom.join(top, oldmiddle);
00536 }
00537
00538 template <typename Graph>
00539 void MaxMatching<Graph>::augment(Node x,
00540 typename Graph::template NodeMap<Node>& ear,
00541 UFE& blossom, UFE& tree) {
00542 Node v=_mate[x];
00543 while ( v!=INVALID ) {
00544
00545 Node u=ear[v];
00546 _mate.set(v,u);
00547 Node tmp=v;
00548 v=_mate[u];
00549 _mate.set(u,tmp);
00550 }
00551 typename UFE::ItemIt it;
00552 for (tree.first(it,blossom.find(x)); tree.valid(it); tree.next(it)) {
00553 if ( position[it] == D ) {
00554 typename UFE::ItemIt b_it;
00555 for (blossom.first(b_it,it); blossom.valid(b_it); blossom.next(b_it)) {
00556 position.set( b_it ,C);
00557 }
00558 blossom.eraseClass(it);
00559 } else position.set( it ,C);
00560 }
00561 tree.eraseClass(x);
00562
00563 }
00564
00566
00567 }
00568
00569 #endif //LEMON_MAX_MATCHING_H