Improved docs.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_MAX_MATCHING_H
20 #define LEMON_MAX_MATCHING_H
23 #include <lemon/bits/invalid.h>
24 #include <lemon/unionfind.h>
25 #include <lemon/graph_utils.h>
29 ///\brief Maximum matching algorithm in undirected graph.
35 ///\brief Edmonds' alternating forest maximum matching algorithm.
37 ///This class provides Edmonds' alternating forest matching
38 ///algorithm. The starting matching (if any) can be passed to the
39 ///algorithm using some of init functions.
41 ///The dual side of a matching is a map of the nodes to
42 ///MaxMatching::DecompType, having values \c D, \c A and \c C
43 ///showing the Gallai-Edmonds decomposition of the graph. The nodes
44 ///in \c D induce a graph with factor-critical components, the nodes
45 ///in \c A form the barrier, and the nodes in \c C induce a graph
46 ///having a perfect matching. This decomposition can be attained by
47 ///calling \c decomposition() after running the algorithm.
49 ///\param Graph The undirected graph type the algorithm runs on.
51 ///\author Jacint Szabo
52 template <typename Graph>
57 typedef typename Graph::Node Node;
58 typedef typename Graph::Edge Edge;
59 typedef typename Graph::UEdge UEdge;
60 typedef typename Graph::UEdgeIt UEdgeIt;
61 typedef typename Graph::NodeIt NodeIt;
62 typedef typename Graph::IncEdgeIt IncEdgeIt;
64 typedef typename Graph::template NodeMap<int> UFECrossRef;
65 typedef UnionFindEnum<UFECrossRef> UFE;
66 typedef std::vector<Node> NV;
68 typedef typename Graph::template NodeMap<int> EFECrossRef;
69 typedef ExtendFindEnum<EFECrossRef> EFE;
73 ///\brief Indicates the Gallai-Edmonds decomposition of the graph.
75 ///Indicates the Gallai-Edmonds decomposition of the graph, which
76 ///shows an upper bound on the size of a maximum matching. The
77 ///nodes with DecompType \c D induce a graph with factor-critical
78 ///components, the nodes in \c A form the canonical barrier, and the
79 ///nodes in \c C induce a graph having a perfect matching.
88 static const int HEUR_density=2;
90 typename Graph::template NodeMap<Node> _mate;
91 typename Graph::template NodeMap<DecompType> position;
95 MaxMatching(const Graph& _g)
96 : g(_g), _mate(_g), position(_g) {}
98 ///\brief Sets the actual matching to the empty matching.
100 ///Sets the actual matching to the empty matching.
103 for(NodeIt v(g); v!=INVALID; ++v) {
104 _mate.set(v,INVALID);
109 ///\brief Finds a greedy matching for initial matching.
111 ///For initial matchig it finds a maximal greedy matching.
113 for(NodeIt v(g); v!=INVALID; ++v) {
114 _mate.set(v,INVALID);
117 for(NodeIt v(g); v!=INVALID; ++v)
118 if ( _mate[v]==INVALID ) {
119 for( IncEdgeIt e(g,v); e!=INVALID ; ++e ) {
120 Node y=g.runningNode(e);
121 if ( _mate[y]==INVALID && y!=v ) {
130 ///\brief Initialize the matching from each nodes' mate.
132 ///Initialize the matching from a \c Node valued \c Node map. This
133 ///map must be \e symmetric, i.e. if \c map[u]==v then \c
134 ///map[v]==u must hold, and \c uv will be an edge of the initial
136 template <typename MateMap>
137 void mateMapInit(MateMap& map) {
138 for(NodeIt v(g); v!=INVALID; ++v) {
144 ///\brief Initialize the matching from a node map with the
145 ///incident matching edges.
147 ///Initialize the matching from an \c UEdge valued \c Node map. \c
148 ///map[v] must be an \c UEdge incident to \c v. This map must have
149 ///the property that if \c g.oppositeNode(u,map[u])==v then \c \c
150 ///g.oppositeNode(v,map[v])==u holds, and now some edge joining \c
151 ///u to \c v will be an edge of the matching.
152 template<typename MatchingMap>
153 void matchingMapInit(MatchingMap& map) {
154 for(NodeIt v(g); v!=INVALID; ++v) {
158 _mate.set(v,g.oppositeNode(v,e));
160 _mate.set(v,INVALID);
164 ///\brief Initialize the matching from the map containing the
165 ///undirected matching edges.
167 ///Initialize the matching from a \c bool valued \c UEdge map. This
168 ///map must have the property that there are no two incident edges
169 ///\c e, \c f with \c map[e]==map[f]==true. The edges \c e with \c
170 ///map[e]==true form the matching.
171 template <typename MatchingMap>
172 void matchingInit(MatchingMap& map) {
173 for(NodeIt v(g); v!=INVALID; ++v) {
174 _mate.set(v,INVALID);
177 for(UEdgeIt e(g); e!=INVALID; ++e) {
188 ///\brief Runs Edmonds' algorithm.
190 ///Runs Edmonds' algorithm for sparse graphs (number of edges <
191 ///2*number of nodes), and a heuristical Edmonds' algorithm with a
192 ///heuristic of postponing shrinks for dense graphs.
194 if (countUEdges(g) < HEUR_density * countNodes(g)) {
204 ///\brief Starts Edmonds' algorithm.
206 ///If runs the original Edmonds' algorithm.
209 typename Graph::template NodeMap<Node> ear(g,INVALID);
210 //undefined for the base nodes of the blossoms (i.e. for the
211 //representative elements of UFE blossom) and for the nodes in C
213 UFECrossRef blossom_base(g);
214 UFE blossom(blossom_base);
215 NV rep(countNodes(g));
217 EFECrossRef tree_base(g);
220 //If these UFE's would be members of the class then also
221 //blossom_base and tree_base should be a member.
223 //We build only one tree and the other vertices uncovered by the
224 //matching belong to C. (They can be considered as singleton
225 //trees.) If this tree can be augmented or no more
226 //grow/augmentation/shrink is possible then we return to this
228 for(NodeIt v(g); v!=INVALID; ++v) {
229 if (position[v]==C && _mate[v]==INVALID) {
230 rep[blossom.insert(v)] = v;
233 normShrink(v, ear, blossom, rep, tree);
238 ///\brief Starts Edmonds' algorithm.
240 ///It runs Edmonds' algorithm with a heuristic of postponing
241 ///shrinks, giving a faster algorithm for dense graphs.
244 typename Graph::template NodeMap<Node> ear(g,INVALID);
245 //undefined for the base nodes of the blossoms (i.e. for the
246 //representative elements of UFE blossom) and for the nodes in C
248 UFECrossRef blossom_base(g);
249 UFE blossom(blossom_base);
250 NV rep(countNodes(g));
252 EFECrossRef tree_base(g);
255 //If these UFE's would be members of the class then also
256 //blossom_base and tree_base should be a member.
258 //We build only one tree and the other vertices uncovered by the
259 //matching belong to C. (They can be considered as singleton
260 //trees.) If this tree can be augmented or no more
261 //grow/augmentation/shrink is possible then we return to this
263 for(NodeIt v(g); v!=INVALID; ++v) {
264 if ( position[v]==C && _mate[v]==INVALID ) {
265 rep[blossom.insert(v)] = v;
268 lateShrink(v, ear, blossom, rep, tree);
275 ///\brief Returns the size of the actual matching stored.
277 ///Returns the size of the actual matching stored. After \ref
278 ///run() it returns the size of a maximum matching in the graph.
281 for(NodeIt v(g); v!=INVALID; ++v) {
282 if ( _mate[v]!=INVALID ) {
290 ///\brief Returns the mate of a node in the actual matching.
292 ///Returns the mate of a \c node in the actual matching.
293 ///Returns INVALID if the \c node is not covered by the actual matching.
294 Node mate(const Node& node) const {
298 ///\brief Returns the matching edge incident to the given node.
300 ///Returns the matching edge of a \c node in the actual matching.
301 ///Returns INVALID if the \c node is not covered by the actual matching.
302 UEdge matchingEdge(const Node& node) const {
303 if (_mate[node] == INVALID) return INVALID;
304 Node n = node < _mate[node] ? node : _mate[node];
305 for (IncEdgeIt e(g, n); e != INVALID; ++e) {
306 if (g.oppositeNode(n, e) == _mate[n]) {
313 /// \brief Returns the class of the node in the Edmonds-Gallai
316 /// Returns the class of the node in the Edmonds-Gallai
318 DecompType decomposition(const Node& n) {
319 return position[n] == A;
322 /// \brief Returns true when the node is in the barrier.
324 /// Returns true when the node is in the barrier.
325 bool barrier(const Node& n) {
326 return position[n] == A;
329 ///\brief Gives back the matching in a \c Node of mates.
331 ///Writes the stored matching to a \c Node valued \c Node map. The
332 ///resulting map will be \e symmetric, i.e. if \c map[u]==v then \c
333 ///map[v]==u will hold, and now \c uv is an edge of the matching.
334 template <typename MateMap>
335 void mateMap(MateMap& map) const {
336 for(NodeIt v(g); v!=INVALID; ++v) {
341 ///\brief Gives back the matching in an \c UEdge valued \c Node
344 ///Writes the stored matching to an \c UEdge valued \c Node
345 ///map. \c map[v] will be an \c UEdge incident to \c v. This
346 ///map will have the property that if \c g.oppositeNode(u,map[u])
347 ///== v then \c map[u]==map[v] holds, and now this edge is an edge
349 template <typename MatchingMap>
350 void matchingMap(MatchingMap& map) const {
351 typename Graph::template NodeMap<bool> todo(g,true);
352 for(NodeIt v(g); v!=INVALID; ++v) {
353 if (_mate[v]!=INVALID && v < _mate[v]) {
355 for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
356 if ( g.runningNode(e) == u ) {
369 ///\brief Gives back the matching in a \c bool valued \c UEdge
372 ///Writes the matching stored to a \c bool valued \c Edge
373 ///map. This map will have the property that there are no two
374 ///incident edges \c e, \c f with \c map[e]==map[f]==true. The
375 ///edges \c e with \c map[e]==true form the matching.
376 template<typename MatchingMap>
377 void matching(MatchingMap& map) const {
378 for(UEdgeIt e(g); e!=INVALID; ++e) map.set(e,false);
380 typename Graph::template NodeMap<bool> todo(g,true);
381 for(NodeIt v(g); v!=INVALID; ++v) {
382 if ( todo[v] && _mate[v]!=INVALID ) {
384 for(IncEdgeIt e(g,v); e!=INVALID; ++e) {
385 if ( g.runningNode(e) == u ) {
397 ///\brief Returns the canonical decomposition of the graph after running
400 ///After calling any run methods of the class, it writes the
401 ///Gallai-Edmonds canonical decomposition of the graph. \c map
402 ///must be a node map of \ref DecompType 's.
403 template <typename DecompositionMap>
404 void decomposition(DecompositionMap& map) const {
405 for(NodeIt v(g); v!=INVALID; ++v) map.set(v,position[v]);
408 ///\brief Returns a barrier on the nodes.
410 ///After calling any run methods of the class, it writes a
411 ///canonical barrier on the nodes. The odd component number of the
412 ///remaining graph minus the barrier size is a lower bound for the
413 ///uncovered nodes in the graph. The \c map must be a node map of
415 template <typename BarrierMap>
416 void barrier(BarrierMap& barrier) {
417 for(NodeIt v(g); v!=INVALID; ++v) barrier.set(v,position[v] == A);
423 void lateShrink(Node v, typename Graph::template NodeMap<Node>& ear,
424 UFE& blossom, NV& rep, EFE& tree) {
425 //We have one tree which we grow, and also shrink but only if it
426 //cannot be postponed. If we augment then we return to the "for"
427 //cycle of runEdmonds().
429 std::queue<Node> Q; //queue of the totally unscanned nodes
432 //queue of the nodes which must be scanned for a possible shrink
434 while ( !Q.empty() ) {
437 for( IncEdgeIt e(g,x); e!= INVALID; ++e ) {
438 Node y=g.runningNode(e);
439 //growOrAugment grows if y is covered by the matching and
440 //augments if not. In this latter case it returns 1.
441 if (position[y]==C &&
442 growOrAugment(y, x, ear, blossom, rep, tree, Q)) return;
447 while ( !R.empty() ) {
451 for( IncEdgeIt e(g,x); e!=INVALID ; ++e ) {
452 Node y=g.runningNode(e);
454 if ( position[y] == D && blossom.find(x) != blossom.find(y) )
455 //Recall that we have only one tree.
456 shrink( x, y, ear, blossom, rep, tree, Q);
458 while ( !Q.empty() ) {
461 for( IncEdgeIt f(g,z); f!= INVALID; ++f ) {
462 Node w=g.runningNode(f);
463 //growOrAugment grows if y is covered by the matching and
464 //augments if not. In this latter case it returns 1.
465 if (position[w]==C &&
466 growOrAugment(w, z, ear, blossom, rep, tree, Q)) return;
471 } // while ( !R.empty() )
474 void normShrink(Node v, typename Graph::template NodeMap<Node>& ear,
475 UFE& blossom, NV& rep, EFE& tree) {
476 //We have one tree, which we grow and shrink. If we augment then we
477 //return to the "for" cycle of runEdmonds().
479 std::queue<Node> Q; //queue of the unscanned nodes
481 while ( !Q.empty() ) {
486 for( IncEdgeIt e(g,x); e!=INVALID; ++e ) {
487 Node y=g.runningNode(e);
489 switch ( position[y] ) {
490 case D: //x and y must be in the same tree
491 if ( blossom.find(x) != blossom.find(y))
492 //x and y are in the same tree
493 shrink(x, y, ear, blossom, rep, tree, Q);
496 //growOrAugment grows if y is covered by the matching and
497 //augments if not. In this latter case it returns 1.
498 if (growOrAugment(y, x, ear, blossom, rep, tree, Q)) return;
506 void shrink(Node x,Node y, typename Graph::template NodeMap<Node>& ear,
507 UFE& blossom, NV& rep, EFE& tree,std::queue<Node>& Q) {
508 //x and y are the two adjacent vertices in two blossoms.
510 typename Graph::template NodeMap<bool> path(g,false);
512 Node b=rep[blossom.find(x)];
515 while ( b!=INVALID ) {
516 b=rep[blossom.find(ear[b])];
519 } //we go until the root through bases of blossoms and odd vertices
522 Node middle=rep[blossom.find(top)];
524 while ( !path[middle] )
525 shrinkStep(top, middle, bottom, ear, blossom, rep, tree, Q);
526 //Until we arrive to a node on the path, we update blossom, tree
527 //and the positions of the odd nodes.
531 middle=rep[blossom.find(top)];
533 Node blossom_base=rep[blossom.find(base)];
534 while ( middle!=blossom_base )
535 shrinkStep(top, middle, bottom, ear, blossom, rep, tree, Q);
536 //Until we arrive to a node on the path, we update blossom, tree
537 //and the positions of the odd nodes.
539 rep[blossom.find(base)] = base;
542 void shrinkStep(Node& top, Node& middle, Node& bottom,
543 typename Graph::template NodeMap<Node>& ear,
544 UFE& blossom, NV& rep, EFE& tree, std::queue<Node>& Q) {
545 //We traverse a blossom and update everything.
549 while ( t!=middle ) {
554 bottom=_mate[middle];
555 position.set(bottom,D);
558 Node oldmiddle=middle;
559 middle=rep[blossom.find(top)];
561 tree.erase(oldmiddle);
562 blossom.insert(bottom);
563 blossom.join(bottom, oldmiddle);
564 blossom.join(top, oldmiddle);
569 bool growOrAugment(Node& y, Node& x, typename Graph::template
570 NodeMap<Node>& ear, UFE& blossom, NV& rep, EFE& tree,
571 std::queue<Node>& Q) {
572 //x is in a blossom in the tree, y is outside. If y is covered by
573 //the matching we grow, otherwise we augment. In this case we
576 if ( _mate[y]!=INVALID ) { //grow
579 rep[blossom.insert(w)] = w;
582 int t = tree.find(rep[blossom.find(x)]);
587 augment(x, ear, blossom, rep, tree);
595 void augment(Node x, typename Graph::template NodeMap<Node>& ear,
596 UFE& blossom, NV& rep, EFE& tree) {
598 while ( v!=INVALID ) {
606 int y = tree.find(rep[blossom.find(x)]);
607 for (typename EFE::ItemIt tit(tree, y); tit != INVALID; ++tit) {
608 if ( position[tit] == D ) {
609 int b = blossom.find(tit);
610 for (typename UFE::ItemIt bit(blossom, b); bit != INVALID; ++bit) {
611 position.set(bit, C);
613 blossom.eraseClass(b);
614 } else position.set(tit, C);
622 } //END OF NAMESPACE LEMON
624 #endif //LEMON_MAX_MATCHING_H