lemon/matching.h
author Alpar Juttner <alpar@cs.elte.hu>
Fri, 15 Apr 2011 09:40:17 +0200
changeset 919 1f1328691a07
parent 651 3adf5e2d1e62
child 875 07ec2b52e53d
permissions -rw-r--r--
Also search for coin libs under ${COIN_ROOT_DIR}/lib/coin (#419)
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2009
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     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.
    12  *
    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
    15  * purpose.
    16  *
    17  */
    18 
    19 #ifndef LEMON_MAX_MATCHING_H
    20 #define LEMON_MAX_MATCHING_H
    21 
    22 #include <vector>
    23 #include <queue>
    24 #include <set>
    25 #include <limits>
    26 
    27 #include <lemon/core.h>
    28 #include <lemon/unionfind.h>
    29 #include <lemon/bin_heap.h>
    30 #include <lemon/maps.h>
    31 
    32 ///\ingroup matching
    33 ///\file
    34 ///\brief Maximum matching algorithms in general graphs.
    35 
    36 namespace lemon {
    37 
    38   /// \ingroup matching
    39   ///
    40   /// \brief Maximum cardinality matching in general graphs
    41   ///
    42   /// This class implements Edmonds' alternating forest matching algorithm
    43   /// for finding a maximum cardinality matching in a general undirected graph.
    44   /// It can be started from an arbitrary initial matching 
    45   /// (the default is the empty one).
    46   ///
    47   /// The dual solution of the problem is a map of the nodes to
    48   /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
    49   /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
    50   /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
    51   /// with factor-critical components, the nodes in \c ODD/A form the
    52   /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
    53   /// a perfect matching. The number of the factor-critical components
    54   /// minus the number of barrier nodes is a lower bound on the
    55   /// unmatched nodes, and the matching is optimal if and only if this bound is
    56   /// tight. This decomposition can be obtained using \ref status() or
    57   /// \ref statusMap() after running the algorithm.
    58   ///
    59   /// \tparam GR The undirected graph type the algorithm runs on.
    60   template <typename GR>
    61   class MaxMatching {
    62   public:
    63 
    64     /// The graph type of the algorithm
    65     typedef GR Graph;
    66     /// The type of the matching map
    67     typedef typename Graph::template NodeMap<typename Graph::Arc>
    68     MatchingMap;
    69 
    70     ///\brief Status constants for Gallai-Edmonds decomposition.
    71     ///
    72     ///These constants are used for indicating the Gallai-Edmonds 
    73     ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
    74     ///induce a subgraph with factor-critical components, the nodes with
    75     ///status \c ODD (or \c A) form the canonical barrier, and the nodes
    76     ///with status \c MATCHED (or \c C) induce a subgraph having a 
    77     ///perfect matching.
    78     enum Status {
    79       EVEN = 1,       ///< = 1. (\c D is an alias for \c EVEN.)
    80       D = 1,
    81       MATCHED = 0,    ///< = 0. (\c C is an alias for \c MATCHED.)
    82       C = 0,
    83       ODD = -1,       ///< = -1. (\c A is an alias for \c ODD.)
    84       A = -1,
    85       UNMATCHED = -2  ///< = -2.
    86     };
    87 
    88     /// The type of the status map
    89     typedef typename Graph::template NodeMap<Status> StatusMap;
    90 
    91   private:
    92 
    93     TEMPLATE_GRAPH_TYPEDEFS(Graph);
    94 
    95     typedef UnionFindEnum<IntNodeMap> BlossomSet;
    96     typedef ExtendFindEnum<IntNodeMap> TreeSet;
    97     typedef RangeMap<Node> NodeIntMap;
    98     typedef MatchingMap EarMap;
    99     typedef std::vector<Node> NodeQueue;
   100 
   101     const Graph& _graph;
   102     MatchingMap* _matching;
   103     StatusMap* _status;
   104 
   105     EarMap* _ear;
   106 
   107     IntNodeMap* _blossom_set_index;
   108     BlossomSet* _blossom_set;
   109     NodeIntMap* _blossom_rep;
   110 
   111     IntNodeMap* _tree_set_index;
   112     TreeSet* _tree_set;
   113 
   114     NodeQueue _node_queue;
   115     int _process, _postpone, _last;
   116 
   117     int _node_num;
   118 
   119   private:
   120 
   121     void createStructures() {
   122       _node_num = countNodes(_graph);
   123       if (!_matching) {
   124         _matching = new MatchingMap(_graph);
   125       }
   126       if (!_status) {
   127         _status = new StatusMap(_graph);
   128       }
   129       if (!_ear) {
   130         _ear = new EarMap(_graph);
   131       }
   132       if (!_blossom_set) {
   133         _blossom_set_index = new IntNodeMap(_graph);
   134         _blossom_set = new BlossomSet(*_blossom_set_index);
   135       }
   136       if (!_blossom_rep) {
   137         _blossom_rep = new NodeIntMap(_node_num);
   138       }
   139       if (!_tree_set) {
   140         _tree_set_index = new IntNodeMap(_graph);
   141         _tree_set = new TreeSet(*_tree_set_index);
   142       }
   143       _node_queue.resize(_node_num);
   144     }
   145 
   146     void destroyStructures() {
   147       if (_matching) {
   148         delete _matching;
   149       }
   150       if (_status) {
   151         delete _status;
   152       }
   153       if (_ear) {
   154         delete _ear;
   155       }
   156       if (_blossom_set) {
   157         delete _blossom_set;
   158         delete _blossom_set_index;
   159       }
   160       if (_blossom_rep) {
   161         delete _blossom_rep;
   162       }
   163       if (_tree_set) {
   164         delete _tree_set_index;
   165         delete _tree_set;
   166       }
   167     }
   168 
   169     void processDense(const Node& n) {
   170       _process = _postpone = _last = 0;
   171       _node_queue[_last++] = n;
   172 
   173       while (_process != _last) {
   174         Node u = _node_queue[_process++];
   175         for (OutArcIt a(_graph, u); a != INVALID; ++a) {
   176           Node v = _graph.target(a);
   177           if ((*_status)[v] == MATCHED) {
   178             extendOnArc(a);
   179           } else if ((*_status)[v] == UNMATCHED) {
   180             augmentOnArc(a);
   181             return;
   182           }
   183         }
   184       }
   185 
   186       while (_postpone != _last) {
   187         Node u = _node_queue[_postpone++];
   188 
   189         for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
   190           Node v = _graph.target(a);
   191 
   192           if ((*_status)[v] == EVEN) {
   193             if (_blossom_set->find(u) != _blossom_set->find(v)) {
   194               shrinkOnEdge(a);
   195             }
   196           }
   197 
   198           while (_process != _last) {
   199             Node w = _node_queue[_process++];
   200             for (OutArcIt b(_graph, w); b != INVALID; ++b) {
   201               Node x = _graph.target(b);
   202               if ((*_status)[x] == MATCHED) {
   203                 extendOnArc(b);
   204               } else if ((*_status)[x] == UNMATCHED) {
   205                 augmentOnArc(b);
   206                 return;
   207               }
   208             }
   209           }
   210         }
   211       }
   212     }
   213 
   214     void processSparse(const Node& n) {
   215       _process = _last = 0;
   216       _node_queue[_last++] = n;
   217       while (_process != _last) {
   218         Node u = _node_queue[_process++];
   219         for (OutArcIt a(_graph, u); a != INVALID; ++a) {
   220           Node v = _graph.target(a);
   221 
   222           if ((*_status)[v] == EVEN) {
   223             if (_blossom_set->find(u) != _blossom_set->find(v)) {
   224               shrinkOnEdge(a);
   225             }
   226           } else if ((*_status)[v] == MATCHED) {
   227             extendOnArc(a);
   228           } else if ((*_status)[v] == UNMATCHED) {
   229             augmentOnArc(a);
   230             return;
   231           }
   232         }
   233       }
   234     }
   235 
   236     void shrinkOnEdge(const Edge& e) {
   237       Node nca = INVALID;
   238 
   239       {
   240         std::set<Node> left_set, right_set;
   241 
   242         Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
   243         left_set.insert(left);
   244 
   245         Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
   246         right_set.insert(right);
   247 
   248         while (true) {
   249           if ((*_matching)[left] == INVALID) break;
   250           left = _graph.target((*_matching)[left]);
   251           left = (*_blossom_rep)[_blossom_set->
   252                                  find(_graph.target((*_ear)[left]))];
   253           if (right_set.find(left) != right_set.end()) {
   254             nca = left;
   255             break;
   256           }
   257           left_set.insert(left);
   258 
   259           if ((*_matching)[right] == INVALID) break;
   260           right = _graph.target((*_matching)[right]);
   261           right = (*_blossom_rep)[_blossom_set->
   262                                   find(_graph.target((*_ear)[right]))];
   263           if (left_set.find(right) != left_set.end()) {
   264             nca = right;
   265             break;
   266           }
   267           right_set.insert(right);
   268         }
   269 
   270         if (nca == INVALID) {
   271           if ((*_matching)[left] == INVALID) {
   272             nca = right;
   273             while (left_set.find(nca) == left_set.end()) {
   274               nca = _graph.target((*_matching)[nca]);
   275               nca =(*_blossom_rep)[_blossom_set->
   276                                    find(_graph.target((*_ear)[nca]))];
   277             }
   278           } else {
   279             nca = left;
   280             while (right_set.find(nca) == right_set.end()) {
   281               nca = _graph.target((*_matching)[nca]);
   282               nca = (*_blossom_rep)[_blossom_set->
   283                                    find(_graph.target((*_ear)[nca]))];
   284             }
   285           }
   286         }
   287       }
   288 
   289       {
   290 
   291         Node node = _graph.u(e);
   292         Arc arc = _graph.direct(e, true);
   293         Node base = (*_blossom_rep)[_blossom_set->find(node)];
   294 
   295         while (base != nca) {
   296           (*_ear)[node] = arc;
   297 
   298           Node n = node;
   299           while (n != base) {
   300             n = _graph.target((*_matching)[n]);
   301             Arc a = (*_ear)[n];
   302             n = _graph.target(a);
   303             (*_ear)[n] = _graph.oppositeArc(a);
   304           }
   305           node = _graph.target((*_matching)[base]);
   306           _tree_set->erase(base);
   307           _tree_set->erase(node);
   308           _blossom_set->insert(node, _blossom_set->find(base));
   309           (*_status)[node] = EVEN;
   310           _node_queue[_last++] = node;
   311           arc = _graph.oppositeArc((*_ear)[node]);
   312           node = _graph.target((*_ear)[node]);
   313           base = (*_blossom_rep)[_blossom_set->find(node)];
   314           _blossom_set->join(_graph.target(arc), base);
   315         }
   316       }
   317 
   318       (*_blossom_rep)[_blossom_set->find(nca)] = nca;
   319 
   320       {
   321 
   322         Node node = _graph.v(e);
   323         Arc arc = _graph.direct(e, false);
   324         Node base = (*_blossom_rep)[_blossom_set->find(node)];
   325 
   326         while (base != nca) {
   327           (*_ear)[node] = arc;
   328 
   329           Node n = node;
   330           while (n != base) {
   331             n = _graph.target((*_matching)[n]);
   332             Arc a = (*_ear)[n];
   333             n = _graph.target(a);
   334             (*_ear)[n] = _graph.oppositeArc(a);
   335           }
   336           node = _graph.target((*_matching)[base]);
   337           _tree_set->erase(base);
   338           _tree_set->erase(node);
   339           _blossom_set->insert(node, _blossom_set->find(base));
   340           (*_status)[node] = EVEN;
   341           _node_queue[_last++] = node;
   342           arc = _graph.oppositeArc((*_ear)[node]);
   343           node = _graph.target((*_ear)[node]);
   344           base = (*_blossom_rep)[_blossom_set->find(node)];
   345           _blossom_set->join(_graph.target(arc), base);
   346         }
   347       }
   348 
   349       (*_blossom_rep)[_blossom_set->find(nca)] = nca;
   350     }
   351 
   352     void extendOnArc(const Arc& a) {
   353       Node base = _graph.source(a);
   354       Node odd = _graph.target(a);
   355 
   356       (*_ear)[odd] = _graph.oppositeArc(a);
   357       Node even = _graph.target((*_matching)[odd]);
   358       (*_blossom_rep)[_blossom_set->insert(even)] = even;
   359       (*_status)[odd] = ODD;
   360       (*_status)[even] = EVEN;
   361       int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
   362       _tree_set->insert(odd, tree);
   363       _tree_set->insert(even, tree);
   364       _node_queue[_last++] = even;
   365 
   366     }
   367 
   368     void augmentOnArc(const Arc& a) {
   369       Node even = _graph.source(a);
   370       Node odd = _graph.target(a);
   371 
   372       int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
   373 
   374       (*_matching)[odd] = _graph.oppositeArc(a);
   375       (*_status)[odd] = MATCHED;
   376 
   377       Arc arc = (*_matching)[even];
   378       (*_matching)[even] = a;
   379 
   380       while (arc != INVALID) {
   381         odd = _graph.target(arc);
   382         arc = (*_ear)[odd];
   383         even = _graph.target(arc);
   384         (*_matching)[odd] = arc;
   385         arc = (*_matching)[even];
   386         (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
   387       }
   388 
   389       for (typename TreeSet::ItemIt it(*_tree_set, tree);
   390            it != INVALID; ++it) {
   391         if ((*_status)[it] == ODD) {
   392           (*_status)[it] = MATCHED;
   393         } else {
   394           int blossom = _blossom_set->find(it);
   395           for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
   396                jt != INVALID; ++jt) {
   397             (*_status)[jt] = MATCHED;
   398           }
   399           _blossom_set->eraseClass(blossom);
   400         }
   401       }
   402       _tree_set->eraseClass(tree);
   403 
   404     }
   405 
   406   public:
   407 
   408     /// \brief Constructor
   409     ///
   410     /// Constructor.
   411     MaxMatching(const Graph& graph)
   412       : _graph(graph), _matching(0), _status(0), _ear(0),
   413         _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
   414         _tree_set_index(0), _tree_set(0) {}
   415 
   416     ~MaxMatching() {
   417       destroyStructures();
   418     }
   419 
   420     /// \name Execution Control
   421     /// The simplest way to execute the algorithm is to use the
   422     /// \c run() member function.\n
   423     /// If you need better control on the execution, you have to call
   424     /// one of the functions \ref init(), \ref greedyInit() or
   425     /// \ref matchingInit() first, then you can start the algorithm with
   426     /// \ref startSparse() or \ref startDense().
   427 
   428     ///@{
   429 
   430     /// \brief Set the initial matching to the empty matching.
   431     ///
   432     /// This function sets the initial matching to the empty matching.
   433     void init() {
   434       createStructures();
   435       for(NodeIt n(_graph); n != INVALID; ++n) {
   436         (*_matching)[n] = INVALID;
   437         (*_status)[n] = UNMATCHED;
   438       }
   439     }
   440 
   441     /// \brief Find an initial matching in a greedy way.
   442     ///
   443     /// This function finds an initial matching in a greedy way.
   444     void greedyInit() {
   445       createStructures();
   446       for (NodeIt n(_graph); n != INVALID; ++n) {
   447         (*_matching)[n] = INVALID;
   448         (*_status)[n] = UNMATCHED;
   449       }
   450       for (NodeIt n(_graph); n != INVALID; ++n) {
   451         if ((*_matching)[n] == INVALID) {
   452           for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
   453             Node v = _graph.target(a);
   454             if ((*_matching)[v] == INVALID && v != n) {
   455               (*_matching)[n] = a;
   456               (*_status)[n] = MATCHED;
   457               (*_matching)[v] = _graph.oppositeArc(a);
   458               (*_status)[v] = MATCHED;
   459               break;
   460             }
   461           }
   462         }
   463       }
   464     }
   465 
   466 
   467     /// \brief Initialize the matching from a map.
   468     ///
   469     /// This function initializes the matching from a \c bool valued edge
   470     /// map. This map should have the property that there are no two incident
   471     /// edges with \c true value, i.e. it really contains a matching.
   472     /// \return \c true if the map contains a matching.
   473     template <typename MatchingMap>
   474     bool matchingInit(const MatchingMap& matching) {
   475       createStructures();
   476 
   477       for (NodeIt n(_graph); n != INVALID; ++n) {
   478         (*_matching)[n] = INVALID;
   479         (*_status)[n] = UNMATCHED;
   480       }
   481       for(EdgeIt e(_graph); e!=INVALID; ++e) {
   482         if (matching[e]) {
   483 
   484           Node u = _graph.u(e);
   485           if ((*_matching)[u] != INVALID) return false;
   486           (*_matching)[u] = _graph.direct(e, true);
   487           (*_status)[u] = MATCHED;
   488 
   489           Node v = _graph.v(e);
   490           if ((*_matching)[v] != INVALID) return false;
   491           (*_matching)[v] = _graph.direct(e, false);
   492           (*_status)[v] = MATCHED;
   493         }
   494       }
   495       return true;
   496     }
   497 
   498     /// \brief Start Edmonds' algorithm
   499     ///
   500     /// This function runs the original Edmonds' algorithm.
   501     ///
   502     /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
   503     /// called before using this function.
   504     void startSparse() {
   505       for(NodeIt n(_graph); n != INVALID; ++n) {
   506         if ((*_status)[n] == UNMATCHED) {
   507           (*_blossom_rep)[_blossom_set->insert(n)] = n;
   508           _tree_set->insert(n);
   509           (*_status)[n] = EVEN;
   510           processSparse(n);
   511         }
   512       }
   513     }
   514 
   515     /// \brief Start Edmonds' algorithm with a heuristic improvement 
   516     /// for dense graphs
   517     ///
   518     /// This function runs Edmonds' algorithm with a heuristic of postponing
   519     /// shrinks, therefore resulting in a faster algorithm for dense graphs.
   520     ///
   521     /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
   522     /// called before using this function.
   523     void startDense() {
   524       for(NodeIt n(_graph); n != INVALID; ++n) {
   525         if ((*_status)[n] == UNMATCHED) {
   526           (*_blossom_rep)[_blossom_set->insert(n)] = n;
   527           _tree_set->insert(n);
   528           (*_status)[n] = EVEN;
   529           processDense(n);
   530         }
   531       }
   532     }
   533 
   534 
   535     /// \brief Run Edmonds' algorithm
   536     ///
   537     /// This function runs Edmonds' algorithm. An additional heuristic of 
   538     /// postponing shrinks is used for relatively dense graphs 
   539     /// (for which <tt>m>=2*n</tt> holds).
   540     void run() {
   541       if (countEdges(_graph) < 2 * countNodes(_graph)) {
   542         greedyInit();
   543         startSparse();
   544       } else {
   545         init();
   546         startDense();
   547       }
   548     }
   549 
   550     /// @}
   551 
   552     /// \name Primal Solution
   553     /// Functions to get the primal solution, i.e. the maximum matching.
   554 
   555     /// @{
   556 
   557     /// \brief Return the size (cardinality) of the matching.
   558     ///
   559     /// This function returns the size (cardinality) of the current matching. 
   560     /// After run() it returns the size of the maximum matching in the graph.
   561     int matchingSize() const {
   562       int size = 0;
   563       for (NodeIt n(_graph); n != INVALID; ++n) {
   564         if ((*_matching)[n] != INVALID) {
   565           ++size;
   566         }
   567       }
   568       return size / 2;
   569     }
   570 
   571     /// \brief Return \c true if the given edge is in the matching.
   572     ///
   573     /// This function returns \c true if the given edge is in the current 
   574     /// matching.
   575     bool matching(const Edge& edge) const {
   576       return edge == (*_matching)[_graph.u(edge)];
   577     }
   578 
   579     /// \brief Return the matching arc (or edge) incident to the given node.
   580     ///
   581     /// This function returns the matching arc (or edge) incident to the
   582     /// given node in the current matching or \c INVALID if the node is 
   583     /// not covered by the matching.
   584     Arc matching(const Node& n) const {
   585       return (*_matching)[n];
   586     }
   587 
   588     /// \brief Return a const reference to the matching map.
   589     ///
   590     /// This function returns a const reference to a node map that stores
   591     /// the matching arc (or edge) incident to each node.
   592     const MatchingMap& matchingMap() const {
   593       return *_matching;
   594     }
   595 
   596     /// \brief Return the mate of the given node.
   597     ///
   598     /// This function returns the mate of the given node in the current 
   599     /// matching or \c INVALID if the node is not covered by the matching.
   600     Node mate(const Node& n) const {
   601       return (*_matching)[n] != INVALID ?
   602         _graph.target((*_matching)[n]) : INVALID;
   603     }
   604 
   605     /// @}
   606 
   607     /// \name Dual Solution
   608     /// Functions to get the dual solution, i.e. the Gallai-Edmonds 
   609     /// decomposition.
   610 
   611     /// @{
   612 
   613     /// \brief Return the status of the given node in the Edmonds-Gallai
   614     /// decomposition.
   615     ///
   616     /// This function returns the \ref Status "status" of the given node
   617     /// in the Edmonds-Gallai decomposition.
   618     Status status(const Node& n) const {
   619       return (*_status)[n];
   620     }
   621 
   622     /// \brief Return a const reference to the status map, which stores
   623     /// the Edmonds-Gallai decomposition.
   624     ///
   625     /// This function returns a const reference to a node map that stores the
   626     /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
   627     const StatusMap& statusMap() const {
   628       return *_status;
   629     }
   630 
   631     /// \brief Return \c true if the given node is in the barrier.
   632     ///
   633     /// This function returns \c true if the given node is in the barrier.
   634     bool barrier(const Node& n) const {
   635       return (*_status)[n] == ODD;
   636     }
   637 
   638     /// @}
   639 
   640   };
   641 
   642   /// \ingroup matching
   643   ///
   644   /// \brief Weighted matching in general graphs
   645   ///
   646   /// This class provides an efficient implementation of Edmond's
   647   /// maximum weighted matching algorithm. The implementation is based
   648   /// on extensive use of priority queues and provides
   649   /// \f$O(nm\log n)\f$ time complexity.
   650   ///
   651   /// The maximum weighted matching problem is to find a subset of the 
   652   /// edges in an undirected graph with maximum overall weight for which 
   653   /// each node has at most one incident edge.
   654   /// It can be formulated with the following linear program.
   655   /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
   656   /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
   657       \quad \forall B\in\mathcal{O}\f] */
   658   /// \f[x_e \ge 0\quad \forall e\in E\f]
   659   /// \f[\max \sum_{e\in E}x_ew_e\f]
   660   /// where \f$\delta(X)\f$ is the set of edges incident to a node in
   661   /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
   662   /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
   663   /// subsets of the nodes.
   664   ///
   665   /// The algorithm calculates an optimal matching and a proof of the
   666   /// optimality. The solution of the dual problem can be used to check
   667   /// the result of the algorithm. The dual linear problem is the
   668   /// following.
   669   /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
   670       z_B \ge w_{uv} \quad \forall uv\in E\f] */
   671   /// \f[y_u \ge 0 \quad \forall u \in V\f]
   672   /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
   673   /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
   674       \frac{\vert B \vert - 1}{2}z_B\f] */
   675   ///
   676   /// The algorithm can be executed with the run() function. 
   677   /// After it the matching (the primal solution) and the dual solution
   678   /// can be obtained using the query functions and the 
   679   /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class, 
   680   /// which is able to iterate on the nodes of a blossom. 
   681   /// If the value type is integer, then the dual solution is multiplied
   682   /// by \ref MaxWeightedMatching::dualScale "4".
   683   ///
   684   /// \tparam GR The undirected graph type the algorithm runs on.
   685   /// \tparam WM The type edge weight map. The default type is 
   686   /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
   687 #ifdef DOXYGEN
   688   template <typename GR, typename WM>
   689 #else
   690   template <typename GR,
   691             typename WM = typename GR::template EdgeMap<int> >
   692 #endif
   693   class MaxWeightedMatching {
   694   public:
   695 
   696     /// The graph type of the algorithm
   697     typedef GR Graph;
   698     /// The type of the edge weight map
   699     typedef WM WeightMap;
   700     /// The value type of the edge weights
   701     typedef typename WeightMap::Value Value;
   702 
   703     /// The type of the matching map
   704     typedef typename Graph::template NodeMap<typename Graph::Arc>
   705     MatchingMap;
   706 
   707     /// \brief Scaling factor for dual solution
   708     ///
   709     /// Scaling factor for dual solution. It is equal to 4 or 1
   710     /// according to the value type.
   711     static const int dualScale =
   712       std::numeric_limits<Value>::is_integer ? 4 : 1;
   713 
   714   private:
   715 
   716     TEMPLATE_GRAPH_TYPEDEFS(Graph);
   717 
   718     typedef typename Graph::template NodeMap<Value> NodePotential;
   719     typedef std::vector<Node> BlossomNodeList;
   720 
   721     struct BlossomVariable {
   722       int begin, end;
   723       Value value;
   724 
   725       BlossomVariable(int _begin, int _end, Value _value)
   726         : begin(_begin), end(_end), value(_value) {}
   727 
   728     };
   729 
   730     typedef std::vector<BlossomVariable> BlossomPotential;
   731 
   732     const Graph& _graph;
   733     const WeightMap& _weight;
   734 
   735     MatchingMap* _matching;
   736 
   737     NodePotential* _node_potential;
   738 
   739     BlossomPotential _blossom_potential;
   740     BlossomNodeList _blossom_node_list;
   741 
   742     int _node_num;
   743     int _blossom_num;
   744 
   745     typedef RangeMap<int> IntIntMap;
   746 
   747     enum Status {
   748       EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
   749     };
   750 
   751     typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
   752     struct BlossomData {
   753       int tree;
   754       Status status;
   755       Arc pred, next;
   756       Value pot, offset;
   757       Node base;
   758     };
   759 
   760     IntNodeMap *_blossom_index;
   761     BlossomSet *_blossom_set;
   762     RangeMap<BlossomData>* _blossom_data;
   763 
   764     IntNodeMap *_node_index;
   765     IntArcMap *_node_heap_index;
   766 
   767     struct NodeData {
   768 
   769       NodeData(IntArcMap& node_heap_index)
   770         : heap(node_heap_index) {}
   771 
   772       int blossom;
   773       Value pot;
   774       BinHeap<Value, IntArcMap> heap;
   775       std::map<int, Arc> heap_index;
   776 
   777       int tree;
   778     };
   779 
   780     RangeMap<NodeData>* _node_data;
   781 
   782     typedef ExtendFindEnum<IntIntMap> TreeSet;
   783 
   784     IntIntMap *_tree_set_index;
   785     TreeSet *_tree_set;
   786 
   787     IntNodeMap *_delta1_index;
   788     BinHeap<Value, IntNodeMap> *_delta1;
   789 
   790     IntIntMap *_delta2_index;
   791     BinHeap<Value, IntIntMap> *_delta2;
   792 
   793     IntEdgeMap *_delta3_index;
   794     BinHeap<Value, IntEdgeMap> *_delta3;
   795 
   796     IntIntMap *_delta4_index;
   797     BinHeap<Value, IntIntMap> *_delta4;
   798 
   799     Value _delta_sum;
   800 
   801     void createStructures() {
   802       _node_num = countNodes(_graph);
   803       _blossom_num = _node_num * 3 / 2;
   804 
   805       if (!_matching) {
   806         _matching = new MatchingMap(_graph);
   807       }
   808 
   809       if (!_node_potential) {
   810         _node_potential = new NodePotential(_graph);
   811       }
   812 
   813       if (!_blossom_set) {
   814         _blossom_index = new IntNodeMap(_graph);
   815         _blossom_set = new BlossomSet(*_blossom_index);
   816         _blossom_data = new RangeMap<BlossomData>(_blossom_num);
   817       } else if (_blossom_data->size() != _blossom_num) {
   818         delete _blossom_data;
   819         _blossom_data = new RangeMap<BlossomData>(_blossom_num);
   820       }
   821 
   822       if (!_node_index) {
   823         _node_index = new IntNodeMap(_graph);
   824         _node_heap_index = new IntArcMap(_graph);
   825         _node_data = new RangeMap<NodeData>(_node_num,
   826                                             NodeData(*_node_heap_index));
   827       } else {
   828         delete _node_data;
   829         _node_data = new RangeMap<NodeData>(_node_num,
   830                                             NodeData(*_node_heap_index));
   831       }
   832 
   833       if (!_tree_set) {
   834         _tree_set_index = new IntIntMap(_blossom_num);
   835         _tree_set = new TreeSet(*_tree_set_index);
   836       } else {
   837         _tree_set_index->resize(_blossom_num);
   838       }
   839 
   840       if (!_delta1) {
   841         _delta1_index = new IntNodeMap(_graph);
   842         _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
   843       }
   844 
   845       if (!_delta2) {
   846         _delta2_index = new IntIntMap(_blossom_num);
   847         _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
   848       } else {
   849         _delta2_index->resize(_blossom_num);
   850       }
   851 
   852       if (!_delta3) {
   853         _delta3_index = new IntEdgeMap(_graph);
   854         _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
   855       }
   856 
   857       if (!_delta4) {
   858         _delta4_index = new IntIntMap(_blossom_num);
   859         _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
   860       } else {
   861         _delta4_index->resize(_blossom_num);
   862       }
   863     }
   864 
   865     void destroyStructures() {
   866       _node_num = countNodes(_graph);
   867       _blossom_num = _node_num * 3 / 2;
   868 
   869       if (_matching) {
   870         delete _matching;
   871       }
   872       if (_node_potential) {
   873         delete _node_potential;
   874       }
   875       if (_blossom_set) {
   876         delete _blossom_index;
   877         delete _blossom_set;
   878         delete _blossom_data;
   879       }
   880 
   881       if (_node_index) {
   882         delete _node_index;
   883         delete _node_heap_index;
   884         delete _node_data;
   885       }
   886 
   887       if (_tree_set) {
   888         delete _tree_set_index;
   889         delete _tree_set;
   890       }
   891       if (_delta1) {
   892         delete _delta1_index;
   893         delete _delta1;
   894       }
   895       if (_delta2) {
   896         delete _delta2_index;
   897         delete _delta2;
   898       }
   899       if (_delta3) {
   900         delete _delta3_index;
   901         delete _delta3;
   902       }
   903       if (_delta4) {
   904         delete _delta4_index;
   905         delete _delta4;
   906       }
   907     }
   908 
   909     void matchedToEven(int blossom, int tree) {
   910       if (_delta2->state(blossom) == _delta2->IN_HEAP) {
   911         _delta2->erase(blossom);
   912       }
   913 
   914       if (!_blossom_set->trivial(blossom)) {
   915         (*_blossom_data)[blossom].pot -=
   916           2 * (_delta_sum - (*_blossom_data)[blossom].offset);
   917       }
   918 
   919       for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
   920            n != INVALID; ++n) {
   921 
   922         _blossom_set->increase(n, std::numeric_limits<Value>::max());
   923         int ni = (*_node_index)[n];
   924 
   925         (*_node_data)[ni].heap.clear();
   926         (*_node_data)[ni].heap_index.clear();
   927 
   928         (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
   929 
   930         _delta1->push(n, (*_node_data)[ni].pot);
   931 
   932         for (InArcIt e(_graph, n); e != INVALID; ++e) {
   933           Node v = _graph.source(e);
   934           int vb = _blossom_set->find(v);
   935           int vi = (*_node_index)[v];
   936 
   937           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
   938             dualScale * _weight[e];
   939 
   940           if ((*_blossom_data)[vb].status == EVEN) {
   941             if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
   942               _delta3->push(e, rw / 2);
   943             }
   944           } else if ((*_blossom_data)[vb].status == UNMATCHED) {
   945             if (_delta3->state(e) != _delta3->IN_HEAP) {
   946               _delta3->push(e, rw);
   947             }
   948           } else {
   949             typename std::map<int, Arc>::iterator it =
   950               (*_node_data)[vi].heap_index.find(tree);
   951 
   952             if (it != (*_node_data)[vi].heap_index.end()) {
   953               if ((*_node_data)[vi].heap[it->second] > rw) {
   954                 (*_node_data)[vi].heap.replace(it->second, e);
   955                 (*_node_data)[vi].heap.decrease(e, rw);
   956                 it->second = e;
   957               }
   958             } else {
   959               (*_node_data)[vi].heap.push(e, rw);
   960               (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
   961             }
   962 
   963             if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
   964               _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
   965 
   966               if ((*_blossom_data)[vb].status == MATCHED) {
   967                 if (_delta2->state(vb) != _delta2->IN_HEAP) {
   968                   _delta2->push(vb, _blossom_set->classPrio(vb) -
   969                                (*_blossom_data)[vb].offset);
   970                 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
   971                            (*_blossom_data)[vb].offset){
   972                   _delta2->decrease(vb, _blossom_set->classPrio(vb) -
   973                                    (*_blossom_data)[vb].offset);
   974                 }
   975               }
   976             }
   977           }
   978         }
   979       }
   980       (*_blossom_data)[blossom].offset = 0;
   981     }
   982 
   983     void matchedToOdd(int blossom) {
   984       if (_delta2->state(blossom) == _delta2->IN_HEAP) {
   985         _delta2->erase(blossom);
   986       }
   987       (*_blossom_data)[blossom].offset += _delta_sum;
   988       if (!_blossom_set->trivial(blossom)) {
   989         _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
   990                      (*_blossom_data)[blossom].offset);
   991       }
   992     }
   993 
   994     void evenToMatched(int blossom, int tree) {
   995       if (!_blossom_set->trivial(blossom)) {
   996         (*_blossom_data)[blossom].pot += 2 * _delta_sum;
   997       }
   998 
   999       for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  1000            n != INVALID; ++n) {
  1001         int ni = (*_node_index)[n];
  1002         (*_node_data)[ni].pot -= _delta_sum;
  1003 
  1004         _delta1->erase(n);
  1005 
  1006         for (InArcIt e(_graph, n); e != INVALID; ++e) {
  1007           Node v = _graph.source(e);
  1008           int vb = _blossom_set->find(v);
  1009           int vi = (*_node_index)[v];
  1010 
  1011           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  1012             dualScale * _weight[e];
  1013 
  1014           if (vb == blossom) {
  1015             if (_delta3->state(e) == _delta3->IN_HEAP) {
  1016               _delta3->erase(e);
  1017             }
  1018           } else if ((*_blossom_data)[vb].status == EVEN) {
  1019 
  1020             if (_delta3->state(e) == _delta3->IN_HEAP) {
  1021               _delta3->erase(e);
  1022             }
  1023 
  1024             int vt = _tree_set->find(vb);
  1025 
  1026             if (vt != tree) {
  1027 
  1028               Arc r = _graph.oppositeArc(e);
  1029 
  1030               typename std::map<int, Arc>::iterator it =
  1031                 (*_node_data)[ni].heap_index.find(vt);
  1032 
  1033               if (it != (*_node_data)[ni].heap_index.end()) {
  1034                 if ((*_node_data)[ni].heap[it->second] > rw) {
  1035                   (*_node_data)[ni].heap.replace(it->second, r);
  1036                   (*_node_data)[ni].heap.decrease(r, rw);
  1037                   it->second = r;
  1038                 }
  1039               } else {
  1040                 (*_node_data)[ni].heap.push(r, rw);
  1041                 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
  1042               }
  1043 
  1044               if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
  1045                 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
  1046 
  1047                 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
  1048                   _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  1049                                (*_blossom_data)[blossom].offset);
  1050                 } else if ((*_delta2)[blossom] >
  1051                            _blossom_set->classPrio(blossom) -
  1052                            (*_blossom_data)[blossom].offset){
  1053                   _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
  1054                                    (*_blossom_data)[blossom].offset);
  1055                 }
  1056               }
  1057             }
  1058 
  1059           } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  1060             if (_delta3->state(e) == _delta3->IN_HEAP) {
  1061               _delta3->erase(e);
  1062             }
  1063           } else {
  1064 
  1065             typename std::map<int, Arc>::iterator it =
  1066               (*_node_data)[vi].heap_index.find(tree);
  1067 
  1068             if (it != (*_node_data)[vi].heap_index.end()) {
  1069               (*_node_data)[vi].heap.erase(it->second);
  1070               (*_node_data)[vi].heap_index.erase(it);
  1071               if ((*_node_data)[vi].heap.empty()) {
  1072                 _blossom_set->increase(v, std::numeric_limits<Value>::max());
  1073               } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
  1074                 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
  1075               }
  1076 
  1077               if ((*_blossom_data)[vb].status == MATCHED) {
  1078                 if (_blossom_set->classPrio(vb) ==
  1079                     std::numeric_limits<Value>::max()) {
  1080                   _delta2->erase(vb);
  1081                 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
  1082                            (*_blossom_data)[vb].offset) {
  1083                   _delta2->increase(vb, _blossom_set->classPrio(vb) -
  1084                                    (*_blossom_data)[vb].offset);
  1085                 }
  1086               }
  1087             }
  1088           }
  1089         }
  1090       }
  1091     }
  1092 
  1093     void oddToMatched(int blossom) {
  1094       (*_blossom_data)[blossom].offset -= _delta_sum;
  1095 
  1096       if (_blossom_set->classPrio(blossom) !=
  1097           std::numeric_limits<Value>::max()) {
  1098         _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  1099                        (*_blossom_data)[blossom].offset);
  1100       }
  1101 
  1102       if (!_blossom_set->trivial(blossom)) {
  1103         _delta4->erase(blossom);
  1104       }
  1105     }
  1106 
  1107     void oddToEven(int blossom, int tree) {
  1108       if (!_blossom_set->trivial(blossom)) {
  1109         _delta4->erase(blossom);
  1110         (*_blossom_data)[blossom].pot -=
  1111           2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
  1112       }
  1113 
  1114       for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  1115            n != INVALID; ++n) {
  1116         int ni = (*_node_index)[n];
  1117 
  1118         _blossom_set->increase(n, std::numeric_limits<Value>::max());
  1119 
  1120         (*_node_data)[ni].heap.clear();
  1121         (*_node_data)[ni].heap_index.clear();
  1122         (*_node_data)[ni].pot +=
  1123           2 * _delta_sum - (*_blossom_data)[blossom].offset;
  1124 
  1125         _delta1->push(n, (*_node_data)[ni].pot);
  1126 
  1127         for (InArcIt e(_graph, n); e != INVALID; ++e) {
  1128           Node v = _graph.source(e);
  1129           int vb = _blossom_set->find(v);
  1130           int vi = (*_node_index)[v];
  1131 
  1132           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  1133             dualScale * _weight[e];
  1134 
  1135           if ((*_blossom_data)[vb].status == EVEN) {
  1136             if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  1137               _delta3->push(e, rw / 2);
  1138             }
  1139           } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  1140             if (_delta3->state(e) != _delta3->IN_HEAP) {
  1141               _delta3->push(e, rw);
  1142             }
  1143           } else {
  1144 
  1145             typename std::map<int, Arc>::iterator it =
  1146               (*_node_data)[vi].heap_index.find(tree);
  1147 
  1148             if (it != (*_node_data)[vi].heap_index.end()) {
  1149               if ((*_node_data)[vi].heap[it->second] > rw) {
  1150                 (*_node_data)[vi].heap.replace(it->second, e);
  1151                 (*_node_data)[vi].heap.decrease(e, rw);
  1152                 it->second = e;
  1153               }
  1154             } else {
  1155               (*_node_data)[vi].heap.push(e, rw);
  1156               (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  1157             }
  1158 
  1159             if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  1160               _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  1161 
  1162               if ((*_blossom_data)[vb].status == MATCHED) {
  1163                 if (_delta2->state(vb) != _delta2->IN_HEAP) {
  1164                   _delta2->push(vb, _blossom_set->classPrio(vb) -
  1165                                (*_blossom_data)[vb].offset);
  1166                 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  1167                            (*_blossom_data)[vb].offset) {
  1168                   _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  1169                                    (*_blossom_data)[vb].offset);
  1170                 }
  1171               }
  1172             }
  1173           }
  1174         }
  1175       }
  1176       (*_blossom_data)[blossom].offset = 0;
  1177     }
  1178 
  1179 
  1180     void matchedToUnmatched(int blossom) {
  1181       if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  1182         _delta2->erase(blossom);
  1183       }
  1184 
  1185       for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  1186            n != INVALID; ++n) {
  1187         int ni = (*_node_index)[n];
  1188 
  1189         _blossom_set->increase(n, std::numeric_limits<Value>::max());
  1190 
  1191         (*_node_data)[ni].heap.clear();
  1192         (*_node_data)[ni].heap_index.clear();
  1193 
  1194         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  1195           Node v = _graph.target(e);
  1196           int vb = _blossom_set->find(v);
  1197           int vi = (*_node_index)[v];
  1198 
  1199           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  1200             dualScale * _weight[e];
  1201 
  1202           if ((*_blossom_data)[vb].status == EVEN) {
  1203             if (_delta3->state(e) != _delta3->IN_HEAP) {
  1204               _delta3->push(e, rw);
  1205             }
  1206           }
  1207         }
  1208       }
  1209     }
  1210 
  1211     void unmatchedToMatched(int blossom) {
  1212       for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  1213            n != INVALID; ++n) {
  1214         int ni = (*_node_index)[n];
  1215 
  1216         for (InArcIt e(_graph, n); e != INVALID; ++e) {
  1217           Node v = _graph.source(e);
  1218           int vb = _blossom_set->find(v);
  1219           int vi = (*_node_index)[v];
  1220 
  1221           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  1222             dualScale * _weight[e];
  1223 
  1224           if (vb == blossom) {
  1225             if (_delta3->state(e) == _delta3->IN_HEAP) {
  1226               _delta3->erase(e);
  1227             }
  1228           } else if ((*_blossom_data)[vb].status == EVEN) {
  1229 
  1230             if (_delta3->state(e) == _delta3->IN_HEAP) {
  1231               _delta3->erase(e);
  1232             }
  1233 
  1234             int vt = _tree_set->find(vb);
  1235 
  1236             Arc r = _graph.oppositeArc(e);
  1237 
  1238             typename std::map<int, Arc>::iterator it =
  1239               (*_node_data)[ni].heap_index.find(vt);
  1240 
  1241             if (it != (*_node_data)[ni].heap_index.end()) {
  1242               if ((*_node_data)[ni].heap[it->second] > rw) {
  1243                 (*_node_data)[ni].heap.replace(it->second, r);
  1244                 (*_node_data)[ni].heap.decrease(r, rw);
  1245                 it->second = r;
  1246               }
  1247             } else {
  1248               (*_node_data)[ni].heap.push(r, rw);
  1249               (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
  1250             }
  1251 
  1252             if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
  1253               _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
  1254 
  1255               if (_delta2->state(blossom) != _delta2->IN_HEAP) {
  1256                 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  1257                              (*_blossom_data)[blossom].offset);
  1258               } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
  1259                          (*_blossom_data)[blossom].offset){
  1260                 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
  1261                                  (*_blossom_data)[blossom].offset);
  1262               }
  1263             }
  1264 
  1265           } else if ((*_blossom_data)[vb].status == UNMATCHED) {
  1266             if (_delta3->state(e) == _delta3->IN_HEAP) {
  1267               _delta3->erase(e);
  1268             }
  1269           }
  1270         }
  1271       }
  1272     }
  1273 
  1274     void alternatePath(int even, int tree) {
  1275       int odd;
  1276 
  1277       evenToMatched(even, tree);
  1278       (*_blossom_data)[even].status = MATCHED;
  1279 
  1280       while ((*_blossom_data)[even].pred != INVALID) {
  1281         odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
  1282         (*_blossom_data)[odd].status = MATCHED;
  1283         oddToMatched(odd);
  1284         (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
  1285 
  1286         even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
  1287         (*_blossom_data)[even].status = MATCHED;
  1288         evenToMatched(even, tree);
  1289         (*_blossom_data)[even].next =
  1290           _graph.oppositeArc((*_blossom_data)[odd].pred);
  1291       }
  1292 
  1293     }
  1294 
  1295     void destroyTree(int tree) {
  1296       for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
  1297         if ((*_blossom_data)[b].status == EVEN) {
  1298           (*_blossom_data)[b].status = MATCHED;
  1299           evenToMatched(b, tree);
  1300         } else if ((*_blossom_data)[b].status == ODD) {
  1301           (*_blossom_data)[b].status = MATCHED;
  1302           oddToMatched(b);
  1303         }
  1304       }
  1305       _tree_set->eraseClass(tree);
  1306     }
  1307 
  1308 
  1309     void unmatchNode(const Node& node) {
  1310       int blossom = _blossom_set->find(node);
  1311       int tree = _tree_set->find(blossom);
  1312 
  1313       alternatePath(blossom, tree);
  1314       destroyTree(tree);
  1315 
  1316       (*_blossom_data)[blossom].status = UNMATCHED;
  1317       (*_blossom_data)[blossom].base = node;
  1318       matchedToUnmatched(blossom);
  1319     }
  1320 
  1321 
  1322     void augmentOnEdge(const Edge& edge) {
  1323 
  1324       int left = _blossom_set->find(_graph.u(edge));
  1325       int right = _blossom_set->find(_graph.v(edge));
  1326 
  1327       if ((*_blossom_data)[left].status == EVEN) {
  1328         int left_tree = _tree_set->find(left);
  1329         alternatePath(left, left_tree);
  1330         destroyTree(left_tree);
  1331       } else {
  1332         (*_blossom_data)[left].status = MATCHED;
  1333         unmatchedToMatched(left);
  1334       }
  1335 
  1336       if ((*_blossom_data)[right].status == EVEN) {
  1337         int right_tree = _tree_set->find(right);
  1338         alternatePath(right, right_tree);
  1339         destroyTree(right_tree);
  1340       } else {
  1341         (*_blossom_data)[right].status = MATCHED;
  1342         unmatchedToMatched(right);
  1343       }
  1344 
  1345       (*_blossom_data)[left].next = _graph.direct(edge, true);
  1346       (*_blossom_data)[right].next = _graph.direct(edge, false);
  1347     }
  1348 
  1349     void extendOnArc(const Arc& arc) {
  1350       int base = _blossom_set->find(_graph.target(arc));
  1351       int tree = _tree_set->find(base);
  1352 
  1353       int odd = _blossom_set->find(_graph.source(arc));
  1354       _tree_set->insert(odd, tree);
  1355       (*_blossom_data)[odd].status = ODD;
  1356       matchedToOdd(odd);
  1357       (*_blossom_data)[odd].pred = arc;
  1358 
  1359       int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
  1360       (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
  1361       _tree_set->insert(even, tree);
  1362       (*_blossom_data)[even].status = EVEN;
  1363       matchedToEven(even, tree);
  1364     }
  1365 
  1366     void shrinkOnEdge(const Edge& edge, int tree) {
  1367       int nca = -1;
  1368       std::vector<int> left_path, right_path;
  1369 
  1370       {
  1371         std::set<int> left_set, right_set;
  1372         int left = _blossom_set->find(_graph.u(edge));
  1373         left_path.push_back(left);
  1374         left_set.insert(left);
  1375 
  1376         int right = _blossom_set->find(_graph.v(edge));
  1377         right_path.push_back(right);
  1378         right_set.insert(right);
  1379 
  1380         while (true) {
  1381 
  1382           if ((*_blossom_data)[left].pred == INVALID) break;
  1383 
  1384           left =
  1385             _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  1386           left_path.push_back(left);
  1387           left =
  1388             _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  1389           left_path.push_back(left);
  1390 
  1391           left_set.insert(left);
  1392 
  1393           if (right_set.find(left) != right_set.end()) {
  1394             nca = left;
  1395             break;
  1396           }
  1397 
  1398           if ((*_blossom_data)[right].pred == INVALID) break;
  1399 
  1400           right =
  1401             _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  1402           right_path.push_back(right);
  1403           right =
  1404             _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  1405           right_path.push_back(right);
  1406 
  1407           right_set.insert(right);
  1408 
  1409           if (left_set.find(right) != left_set.end()) {
  1410             nca = right;
  1411             break;
  1412           }
  1413 
  1414         }
  1415 
  1416         if (nca == -1) {
  1417           if ((*_blossom_data)[left].pred == INVALID) {
  1418             nca = right;
  1419             while (left_set.find(nca) == left_set.end()) {
  1420               nca =
  1421                 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  1422               right_path.push_back(nca);
  1423               nca =
  1424                 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  1425               right_path.push_back(nca);
  1426             }
  1427           } else {
  1428             nca = left;
  1429             while (right_set.find(nca) == right_set.end()) {
  1430               nca =
  1431                 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  1432               left_path.push_back(nca);
  1433               nca =
  1434                 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  1435               left_path.push_back(nca);
  1436             }
  1437           }
  1438         }
  1439       }
  1440 
  1441       std::vector<int> subblossoms;
  1442       Arc prev;
  1443 
  1444       prev = _graph.direct(edge, true);
  1445       for (int i = 0; left_path[i] != nca; i += 2) {
  1446         subblossoms.push_back(left_path[i]);
  1447         (*_blossom_data)[left_path[i]].next = prev;
  1448         _tree_set->erase(left_path[i]);
  1449 
  1450         subblossoms.push_back(left_path[i + 1]);
  1451         (*_blossom_data)[left_path[i + 1]].status = EVEN;
  1452         oddToEven(left_path[i + 1], tree);
  1453         _tree_set->erase(left_path[i + 1]);
  1454         prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
  1455       }
  1456 
  1457       int k = 0;
  1458       while (right_path[k] != nca) ++k;
  1459 
  1460       subblossoms.push_back(nca);
  1461       (*_blossom_data)[nca].next = prev;
  1462 
  1463       for (int i = k - 2; i >= 0; i -= 2) {
  1464         subblossoms.push_back(right_path[i + 1]);
  1465         (*_blossom_data)[right_path[i + 1]].status = EVEN;
  1466         oddToEven(right_path[i + 1], tree);
  1467         _tree_set->erase(right_path[i + 1]);
  1468 
  1469         (*_blossom_data)[right_path[i + 1]].next =
  1470           (*_blossom_data)[right_path[i + 1]].pred;
  1471 
  1472         subblossoms.push_back(right_path[i]);
  1473         _tree_set->erase(right_path[i]);
  1474       }
  1475 
  1476       int surface =
  1477         _blossom_set->join(subblossoms.begin(), subblossoms.end());
  1478 
  1479       for (int i = 0; i < int(subblossoms.size()); ++i) {
  1480         if (!_blossom_set->trivial(subblossoms[i])) {
  1481           (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
  1482         }
  1483         (*_blossom_data)[subblossoms[i]].status = MATCHED;
  1484       }
  1485 
  1486       (*_blossom_data)[surface].pot = -2 * _delta_sum;
  1487       (*_blossom_data)[surface].offset = 0;
  1488       (*_blossom_data)[surface].status = EVEN;
  1489       (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
  1490       (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
  1491 
  1492       _tree_set->insert(surface, tree);
  1493       _tree_set->erase(nca);
  1494     }
  1495 
  1496     void splitBlossom(int blossom) {
  1497       Arc next = (*_blossom_data)[blossom].next;
  1498       Arc pred = (*_blossom_data)[blossom].pred;
  1499 
  1500       int tree = _tree_set->find(blossom);
  1501 
  1502       (*_blossom_data)[blossom].status = MATCHED;
  1503       oddToMatched(blossom);
  1504       if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  1505         _delta2->erase(blossom);
  1506       }
  1507 
  1508       std::vector<int> subblossoms;
  1509       _blossom_set->split(blossom, std::back_inserter(subblossoms));
  1510 
  1511       Value offset = (*_blossom_data)[blossom].offset;
  1512       int b = _blossom_set->find(_graph.source(pred));
  1513       int d = _blossom_set->find(_graph.source(next));
  1514 
  1515       int ib = -1, id = -1;
  1516       for (int i = 0; i < int(subblossoms.size()); ++i) {
  1517         if (subblossoms[i] == b) ib = i;
  1518         if (subblossoms[i] == d) id = i;
  1519 
  1520         (*_blossom_data)[subblossoms[i]].offset = offset;
  1521         if (!_blossom_set->trivial(subblossoms[i])) {
  1522           (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
  1523         }
  1524         if (_blossom_set->classPrio(subblossoms[i]) !=
  1525             std::numeric_limits<Value>::max()) {
  1526           _delta2->push(subblossoms[i],
  1527                         _blossom_set->classPrio(subblossoms[i]) -
  1528                         (*_blossom_data)[subblossoms[i]].offset);
  1529         }
  1530       }
  1531 
  1532       if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
  1533         for (int i = (id + 1) % subblossoms.size();
  1534              i != ib; i = (i + 2) % subblossoms.size()) {
  1535           int sb = subblossoms[i];
  1536           int tb = subblossoms[(i + 1) % subblossoms.size()];
  1537           (*_blossom_data)[sb].next =
  1538             _graph.oppositeArc((*_blossom_data)[tb].next);
  1539         }
  1540 
  1541         for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
  1542           int sb = subblossoms[i];
  1543           int tb = subblossoms[(i + 1) % subblossoms.size()];
  1544           int ub = subblossoms[(i + 2) % subblossoms.size()];
  1545 
  1546           (*_blossom_data)[sb].status = ODD;
  1547           matchedToOdd(sb);
  1548           _tree_set->insert(sb, tree);
  1549           (*_blossom_data)[sb].pred = pred;
  1550           (*_blossom_data)[sb].next =
  1551                            _graph.oppositeArc((*_blossom_data)[tb].next);
  1552 
  1553           pred = (*_blossom_data)[ub].next;
  1554 
  1555           (*_blossom_data)[tb].status = EVEN;
  1556           matchedToEven(tb, tree);
  1557           _tree_set->insert(tb, tree);
  1558           (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
  1559         }
  1560 
  1561         (*_blossom_data)[subblossoms[id]].status = ODD;
  1562         matchedToOdd(subblossoms[id]);
  1563         _tree_set->insert(subblossoms[id], tree);
  1564         (*_blossom_data)[subblossoms[id]].next = next;
  1565         (*_blossom_data)[subblossoms[id]].pred = pred;
  1566 
  1567       } else {
  1568 
  1569         for (int i = (ib + 1) % subblossoms.size();
  1570              i != id; i = (i + 2) % subblossoms.size()) {
  1571           int sb = subblossoms[i];
  1572           int tb = subblossoms[(i + 1) % subblossoms.size()];
  1573           (*_blossom_data)[sb].next =
  1574             _graph.oppositeArc((*_blossom_data)[tb].next);
  1575         }
  1576 
  1577         for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
  1578           int sb = subblossoms[i];
  1579           int tb = subblossoms[(i + 1) % subblossoms.size()];
  1580           int ub = subblossoms[(i + 2) % subblossoms.size()];
  1581 
  1582           (*_blossom_data)[sb].status = ODD;
  1583           matchedToOdd(sb);
  1584           _tree_set->insert(sb, tree);
  1585           (*_blossom_data)[sb].next = next;
  1586           (*_blossom_data)[sb].pred =
  1587             _graph.oppositeArc((*_blossom_data)[tb].next);
  1588 
  1589           (*_blossom_data)[tb].status = EVEN;
  1590           matchedToEven(tb, tree);
  1591           _tree_set->insert(tb, tree);
  1592           (*_blossom_data)[tb].pred =
  1593             (*_blossom_data)[tb].next =
  1594             _graph.oppositeArc((*_blossom_data)[ub].next);
  1595           next = (*_blossom_data)[ub].next;
  1596         }
  1597 
  1598         (*_blossom_data)[subblossoms[ib]].status = ODD;
  1599         matchedToOdd(subblossoms[ib]);
  1600         _tree_set->insert(subblossoms[ib], tree);
  1601         (*_blossom_data)[subblossoms[ib]].next = next;
  1602         (*_blossom_data)[subblossoms[ib]].pred = pred;
  1603       }
  1604       _tree_set->erase(blossom);
  1605     }
  1606 
  1607     void extractBlossom(int blossom, const Node& base, const Arc& matching) {
  1608       if (_blossom_set->trivial(blossom)) {
  1609         int bi = (*_node_index)[base];
  1610         Value pot = (*_node_data)[bi].pot;
  1611 
  1612         (*_matching)[base] = matching;
  1613         _blossom_node_list.push_back(base);
  1614         (*_node_potential)[base] = pot;
  1615       } else {
  1616 
  1617         Value pot = (*_blossom_data)[blossom].pot;
  1618         int bn = _blossom_node_list.size();
  1619 
  1620         std::vector<int> subblossoms;
  1621         _blossom_set->split(blossom, std::back_inserter(subblossoms));
  1622         int b = _blossom_set->find(base);
  1623         int ib = -1;
  1624         for (int i = 0; i < int(subblossoms.size()); ++i) {
  1625           if (subblossoms[i] == b) { ib = i; break; }
  1626         }
  1627 
  1628         for (int i = 1; i < int(subblossoms.size()); i += 2) {
  1629           int sb = subblossoms[(ib + i) % subblossoms.size()];
  1630           int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
  1631 
  1632           Arc m = (*_blossom_data)[tb].next;
  1633           extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
  1634           extractBlossom(tb, _graph.source(m), m);
  1635         }
  1636         extractBlossom(subblossoms[ib], base, matching);
  1637 
  1638         int en = _blossom_node_list.size();
  1639 
  1640         _blossom_potential.push_back(BlossomVariable(bn, en, pot));
  1641       }
  1642     }
  1643 
  1644     void extractMatching() {
  1645       std::vector<int> blossoms;
  1646       for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
  1647         blossoms.push_back(c);
  1648       }
  1649 
  1650       for (int i = 0; i < int(blossoms.size()); ++i) {
  1651         if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
  1652 
  1653           Value offset = (*_blossom_data)[blossoms[i]].offset;
  1654           (*_blossom_data)[blossoms[i]].pot += 2 * offset;
  1655           for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
  1656                n != INVALID; ++n) {
  1657             (*_node_data)[(*_node_index)[n]].pot -= offset;
  1658           }
  1659 
  1660           Arc matching = (*_blossom_data)[blossoms[i]].next;
  1661           Node base = _graph.source(matching);
  1662           extractBlossom(blossoms[i], base, matching);
  1663         } else {
  1664           Node base = (*_blossom_data)[blossoms[i]].base;
  1665           extractBlossom(blossoms[i], base, INVALID);
  1666         }
  1667       }
  1668     }
  1669 
  1670   public:
  1671 
  1672     /// \brief Constructor
  1673     ///
  1674     /// Constructor.
  1675     MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
  1676       : _graph(graph), _weight(weight), _matching(0),
  1677         _node_potential(0), _blossom_potential(), _blossom_node_list(),
  1678         _node_num(0), _blossom_num(0),
  1679 
  1680         _blossom_index(0), _blossom_set(0), _blossom_data(0),
  1681         _node_index(0), _node_heap_index(0), _node_data(0),
  1682         _tree_set_index(0), _tree_set(0),
  1683 
  1684         _delta1_index(0), _delta1(0),
  1685         _delta2_index(0), _delta2(0),
  1686         _delta3_index(0), _delta3(0),
  1687         _delta4_index(0), _delta4(0),
  1688 
  1689         _delta_sum() {}
  1690 
  1691     ~MaxWeightedMatching() {
  1692       destroyStructures();
  1693     }
  1694 
  1695     /// \name Execution Control
  1696     /// The simplest way to execute the algorithm is to use the
  1697     /// \ref run() member function.
  1698 
  1699     ///@{
  1700 
  1701     /// \brief Initialize the algorithm
  1702     ///
  1703     /// This function initializes the algorithm.
  1704     void init() {
  1705       createStructures();
  1706 
  1707       _blossom_node_list.clear();
  1708       _blossom_potential.clear();
  1709 
  1710       for (ArcIt e(_graph); e != INVALID; ++e) {
  1711         (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
  1712       }
  1713       for (NodeIt n(_graph); n != INVALID; ++n) {
  1714         (*_delta1_index)[n] = _delta1->PRE_HEAP;
  1715       }
  1716       for (EdgeIt e(_graph); e != INVALID; ++e) {
  1717         (*_delta3_index)[e] = _delta3->PRE_HEAP;
  1718       }
  1719       for (int i = 0; i < _blossom_num; ++i) {
  1720         (*_delta2_index)[i] = _delta2->PRE_HEAP;
  1721         (*_delta4_index)[i] = _delta4->PRE_HEAP;
  1722       }
  1723       
  1724       _delta1->clear();
  1725       _delta2->clear();
  1726       _delta3->clear();
  1727       _delta4->clear();
  1728       _blossom_set->clear();
  1729       _tree_set->clear();
  1730 
  1731       int index = 0;
  1732       for (NodeIt n(_graph); n != INVALID; ++n) {
  1733         Value max = 0;
  1734         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  1735           if (_graph.target(e) == n) continue;
  1736           if ((dualScale * _weight[e]) / 2 > max) {
  1737             max = (dualScale * _weight[e]) / 2;
  1738           }
  1739         }
  1740         (*_node_index)[n] = index;
  1741         (*_node_data)[index].heap_index.clear();
  1742         (*_node_data)[index].heap.clear();
  1743         (*_node_data)[index].pot = max;
  1744         _delta1->push(n, max);
  1745         int blossom =
  1746           _blossom_set->insert(n, std::numeric_limits<Value>::max());
  1747 
  1748         _tree_set->insert(blossom);
  1749 
  1750         (*_blossom_data)[blossom].status = EVEN;
  1751         (*_blossom_data)[blossom].pred = INVALID;
  1752         (*_blossom_data)[blossom].next = INVALID;
  1753         (*_blossom_data)[blossom].pot = 0;
  1754         (*_blossom_data)[blossom].offset = 0;
  1755         ++index;
  1756       }
  1757       for (EdgeIt e(_graph); e != INVALID; ++e) {
  1758         int si = (*_node_index)[_graph.u(e)];
  1759         int ti = (*_node_index)[_graph.v(e)];
  1760         if (_graph.u(e) != _graph.v(e)) {
  1761           _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
  1762                             dualScale * _weight[e]) / 2);
  1763         }
  1764       }
  1765     }
  1766 
  1767     /// \brief Start the algorithm
  1768     ///
  1769     /// This function starts the algorithm.
  1770     ///
  1771     /// \pre \ref init() must be called before using this function.
  1772     void start() {
  1773       enum OpType {
  1774         D1, D2, D3, D4
  1775       };
  1776 
  1777       int unmatched = _node_num;
  1778       while (unmatched > 0) {
  1779         Value d1 = !_delta1->empty() ?
  1780           _delta1->prio() : std::numeric_limits<Value>::max();
  1781 
  1782         Value d2 = !_delta2->empty() ?
  1783           _delta2->prio() : std::numeric_limits<Value>::max();
  1784 
  1785         Value d3 = !_delta3->empty() ?
  1786           _delta3->prio() : std::numeric_limits<Value>::max();
  1787 
  1788         Value d4 = !_delta4->empty() ?
  1789           _delta4->prio() : std::numeric_limits<Value>::max();
  1790 
  1791         _delta_sum = d1; OpType ot = D1;
  1792         if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
  1793         if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
  1794         if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
  1795 
  1796 
  1797         switch (ot) {
  1798         case D1:
  1799           {
  1800             Node n = _delta1->top();
  1801             unmatchNode(n);
  1802             --unmatched;
  1803           }
  1804           break;
  1805         case D2:
  1806           {
  1807             int blossom = _delta2->top();
  1808             Node n = _blossom_set->classTop(blossom);
  1809             Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
  1810             extendOnArc(e);
  1811           }
  1812           break;
  1813         case D3:
  1814           {
  1815             Edge e = _delta3->top();
  1816 
  1817             int left_blossom = _blossom_set->find(_graph.u(e));
  1818             int right_blossom = _blossom_set->find(_graph.v(e));
  1819 
  1820             if (left_blossom == right_blossom) {
  1821               _delta3->pop();
  1822             } else {
  1823               int left_tree;
  1824               if ((*_blossom_data)[left_blossom].status == EVEN) {
  1825                 left_tree = _tree_set->find(left_blossom);
  1826               } else {
  1827                 left_tree = -1;
  1828                 ++unmatched;
  1829               }
  1830               int right_tree;
  1831               if ((*_blossom_data)[right_blossom].status == EVEN) {
  1832                 right_tree = _tree_set->find(right_blossom);
  1833               } else {
  1834                 right_tree = -1;
  1835                 ++unmatched;
  1836               }
  1837 
  1838               if (left_tree == right_tree) {
  1839                 shrinkOnEdge(e, left_tree);
  1840               } else {
  1841                 augmentOnEdge(e);
  1842                 unmatched -= 2;
  1843               }
  1844             }
  1845           } break;
  1846         case D4:
  1847           splitBlossom(_delta4->top());
  1848           break;
  1849         }
  1850       }
  1851       extractMatching();
  1852     }
  1853 
  1854     /// \brief Run the algorithm.
  1855     ///
  1856     /// This method runs the \c %MaxWeightedMatching algorithm.
  1857     ///
  1858     /// \note mwm.run() is just a shortcut of the following code.
  1859     /// \code
  1860     ///   mwm.init();
  1861     ///   mwm.start();
  1862     /// \endcode
  1863     void run() {
  1864       init();
  1865       start();
  1866     }
  1867 
  1868     /// @}
  1869 
  1870     /// \name Primal Solution
  1871     /// Functions to get the primal solution, i.e. the maximum weighted 
  1872     /// matching.\n
  1873     /// Either \ref run() or \ref start() function should be called before
  1874     /// using them.
  1875 
  1876     /// @{
  1877 
  1878     /// \brief Return the weight of the matching.
  1879     ///
  1880     /// This function returns the weight of the found matching.
  1881     ///
  1882     /// \pre Either run() or start() must be called before using this function.
  1883     Value matchingWeight() const {
  1884       Value sum = 0;
  1885       for (NodeIt n(_graph); n != INVALID; ++n) {
  1886         if ((*_matching)[n] != INVALID) {
  1887           sum += _weight[(*_matching)[n]];
  1888         }
  1889       }
  1890       return sum /= 2;
  1891     }
  1892 
  1893     /// \brief Return the size (cardinality) of the matching.
  1894     ///
  1895     /// This function returns the size (cardinality) of the found matching.
  1896     ///
  1897     /// \pre Either run() or start() must be called before using this function.
  1898     int matchingSize() const {
  1899       int num = 0;
  1900       for (NodeIt n(_graph); n != INVALID; ++n) {
  1901         if ((*_matching)[n] != INVALID) {
  1902           ++num;
  1903         }
  1904       }
  1905       return num /= 2;
  1906     }
  1907 
  1908     /// \brief Return \c true if the given edge is in the matching.
  1909     ///
  1910     /// This function returns \c true if the given edge is in the found 
  1911     /// matching.
  1912     ///
  1913     /// \pre Either run() or start() must be called before using this function.
  1914     bool matching(const Edge& edge) const {
  1915       return edge == (*_matching)[_graph.u(edge)];
  1916     }
  1917 
  1918     /// \brief Return the matching arc (or edge) incident to the given node.
  1919     ///
  1920     /// This function returns the matching arc (or edge) incident to the
  1921     /// given node in the found matching or \c INVALID if the node is 
  1922     /// not covered by the matching.
  1923     ///
  1924     /// \pre Either run() or start() must be called before using this function.
  1925     Arc matching(const Node& node) const {
  1926       return (*_matching)[node];
  1927     }
  1928 
  1929     /// \brief Return a const reference to the matching map.
  1930     ///
  1931     /// This function returns a const reference to a node map that stores
  1932     /// the matching arc (or edge) incident to each node.
  1933     const MatchingMap& matchingMap() const {
  1934       return *_matching;
  1935     }
  1936 
  1937     /// \brief Return the mate of the given node.
  1938     ///
  1939     /// This function returns the mate of the given node in the found 
  1940     /// matching or \c INVALID if the node is not covered by the matching.
  1941     ///
  1942     /// \pre Either run() or start() must be called before using this function.
  1943     Node mate(const Node& node) const {
  1944       return (*_matching)[node] != INVALID ?
  1945         _graph.target((*_matching)[node]) : INVALID;
  1946     }
  1947 
  1948     /// @}
  1949 
  1950     /// \name Dual Solution
  1951     /// Functions to get the dual solution.\n
  1952     /// Either \ref run() or \ref start() function should be called before
  1953     /// using them.
  1954 
  1955     /// @{
  1956 
  1957     /// \brief Return the value of the dual solution.
  1958     ///
  1959     /// This function returns the value of the dual solution. 
  1960     /// It should be equal to the primal value scaled by \ref dualScale 
  1961     /// "dual scale".
  1962     ///
  1963     /// \pre Either run() or start() must be called before using this function.
  1964     Value dualValue() const {
  1965       Value sum = 0;
  1966       for (NodeIt n(_graph); n != INVALID; ++n) {
  1967         sum += nodeValue(n);
  1968       }
  1969       for (int i = 0; i < blossomNum(); ++i) {
  1970         sum += blossomValue(i) * (blossomSize(i) / 2);
  1971       }
  1972       return sum;
  1973     }
  1974 
  1975     /// \brief Return the dual value (potential) of the given node.
  1976     ///
  1977     /// This function returns the dual value (potential) of the given node.
  1978     ///
  1979     /// \pre Either run() or start() must be called before using this function.
  1980     Value nodeValue(const Node& n) const {
  1981       return (*_node_potential)[n];
  1982     }
  1983 
  1984     /// \brief Return the number of the blossoms in the basis.
  1985     ///
  1986     /// This function returns the number of the blossoms in the basis.
  1987     ///
  1988     /// \pre Either run() or start() must be called before using this function.
  1989     /// \see BlossomIt
  1990     int blossomNum() const {
  1991       return _blossom_potential.size();
  1992     }
  1993 
  1994     /// \brief Return the number of the nodes in the given blossom.
  1995     ///
  1996     /// This function returns the number of the nodes in the given blossom.
  1997     ///
  1998     /// \pre Either run() or start() must be called before using this function.
  1999     /// \see BlossomIt
  2000     int blossomSize(int k) const {
  2001       return _blossom_potential[k].end - _blossom_potential[k].begin;
  2002     }
  2003 
  2004     /// \brief Return the dual value (ptential) of the given blossom.
  2005     ///
  2006     /// This function returns the dual value (ptential) of the given blossom.
  2007     ///
  2008     /// \pre Either run() or start() must be called before using this function.
  2009     Value blossomValue(int k) const {
  2010       return _blossom_potential[k].value;
  2011     }
  2012 
  2013     /// \brief Iterator for obtaining the nodes of a blossom.
  2014     ///
  2015     /// This class provides an iterator for obtaining the nodes of the 
  2016     /// given blossom. It lists a subset of the nodes.
  2017     /// Before using this iterator, you must allocate a 
  2018     /// MaxWeightedMatching class and execute it.
  2019     class BlossomIt {
  2020     public:
  2021 
  2022       /// \brief Constructor.
  2023       ///
  2024       /// Constructor to get the nodes of the given variable.
  2025       ///
  2026       /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or 
  2027       /// \ref MaxWeightedMatching::start() "algorithm.start()" must be 
  2028       /// called before initializing this iterator.
  2029       BlossomIt(const MaxWeightedMatching& algorithm, int variable)
  2030         : _algorithm(&algorithm)
  2031       {
  2032         _index = _algorithm->_blossom_potential[variable].begin;
  2033         _last = _algorithm->_blossom_potential[variable].end;
  2034       }
  2035 
  2036       /// \brief Conversion to \c Node.
  2037       ///
  2038       /// Conversion to \c Node.
  2039       operator Node() const {
  2040         return _algorithm->_blossom_node_list[_index];
  2041       }
  2042 
  2043       /// \brief Increment operator.
  2044       ///
  2045       /// Increment operator.
  2046       BlossomIt& operator++() {
  2047         ++_index;
  2048         return *this;
  2049       }
  2050 
  2051       /// \brief Validity checking
  2052       ///
  2053       /// Checks whether the iterator is invalid.
  2054       bool operator==(Invalid) const { return _index == _last; }
  2055 
  2056       /// \brief Validity checking
  2057       ///
  2058       /// Checks whether the iterator is valid.
  2059       bool operator!=(Invalid) const { return _index != _last; }
  2060 
  2061     private:
  2062       const MaxWeightedMatching* _algorithm;
  2063       int _last;
  2064       int _index;
  2065     };
  2066 
  2067     /// @}
  2068 
  2069   };
  2070 
  2071   /// \ingroup matching
  2072   ///
  2073   /// \brief Weighted perfect matching in general graphs
  2074   ///
  2075   /// This class provides an efficient implementation of Edmond's
  2076   /// maximum weighted perfect matching algorithm. The implementation
  2077   /// is based on extensive use of priority queues and provides
  2078   /// \f$O(nm\log n)\f$ time complexity.
  2079   ///
  2080   /// The maximum weighted perfect matching problem is to find a subset of 
  2081   /// the edges in an undirected graph with maximum overall weight for which 
  2082   /// each node has exactly one incident edge.
  2083   /// It can be formulated with the following linear program.
  2084   /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
  2085   /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
  2086       \quad \forall B\in\mathcal{O}\f] */
  2087   /// \f[x_e \ge 0\quad \forall e\in E\f]
  2088   /// \f[\max \sum_{e\in E}x_ew_e\f]
  2089   /// where \f$\delta(X)\f$ is the set of edges incident to a node in
  2090   /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
  2091   /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
  2092   /// subsets of the nodes.
  2093   ///
  2094   /// The algorithm calculates an optimal matching and a proof of the
  2095   /// optimality. The solution of the dual problem can be used to check
  2096   /// the result of the algorithm. The dual linear problem is the
  2097   /// following.
  2098   /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
  2099       w_{uv} \quad \forall uv\in E\f] */
  2100   /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
  2101   /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
  2102       \frac{\vert B \vert - 1}{2}z_B\f] */
  2103   ///
  2104   /// The algorithm can be executed with the run() function. 
  2105   /// After it the matching (the primal solution) and the dual solution
  2106   /// can be obtained using the query functions and the 
  2107   /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class, 
  2108   /// which is able to iterate on the nodes of a blossom. 
  2109   /// If the value type is integer, then the dual solution is multiplied
  2110   /// by \ref MaxWeightedMatching::dualScale "4".
  2111   ///
  2112   /// \tparam GR The undirected graph type the algorithm runs on.
  2113   /// \tparam WM The type edge weight map. The default type is 
  2114   /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
  2115 #ifdef DOXYGEN
  2116   template <typename GR, typename WM>
  2117 #else
  2118   template <typename GR,
  2119             typename WM = typename GR::template EdgeMap<int> >
  2120 #endif
  2121   class MaxWeightedPerfectMatching {
  2122   public:
  2123 
  2124     /// The graph type of the algorithm
  2125     typedef GR Graph;
  2126     /// The type of the edge weight map
  2127     typedef WM WeightMap;
  2128     /// The value type of the edge weights
  2129     typedef typename WeightMap::Value Value;
  2130 
  2131     /// \brief Scaling factor for dual solution
  2132     ///
  2133     /// Scaling factor for dual solution, it is equal to 4 or 1
  2134     /// according to the value type.
  2135     static const int dualScale =
  2136       std::numeric_limits<Value>::is_integer ? 4 : 1;
  2137 
  2138     /// The type of the matching map
  2139     typedef typename Graph::template NodeMap<typename Graph::Arc>
  2140     MatchingMap;
  2141 
  2142   private:
  2143 
  2144     TEMPLATE_GRAPH_TYPEDEFS(Graph);
  2145 
  2146     typedef typename Graph::template NodeMap<Value> NodePotential;
  2147     typedef std::vector<Node> BlossomNodeList;
  2148 
  2149     struct BlossomVariable {
  2150       int begin, end;
  2151       Value value;
  2152 
  2153       BlossomVariable(int _begin, int _end, Value _value)
  2154         : begin(_begin), end(_end), value(_value) {}
  2155 
  2156     };
  2157 
  2158     typedef std::vector<BlossomVariable> BlossomPotential;
  2159 
  2160     const Graph& _graph;
  2161     const WeightMap& _weight;
  2162 
  2163     MatchingMap* _matching;
  2164 
  2165     NodePotential* _node_potential;
  2166 
  2167     BlossomPotential _blossom_potential;
  2168     BlossomNodeList _blossom_node_list;
  2169 
  2170     int _node_num;
  2171     int _blossom_num;
  2172 
  2173     typedef RangeMap<int> IntIntMap;
  2174 
  2175     enum Status {
  2176       EVEN = -1, MATCHED = 0, ODD = 1
  2177     };
  2178 
  2179     typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
  2180     struct BlossomData {
  2181       int tree;
  2182       Status status;
  2183       Arc pred, next;
  2184       Value pot, offset;
  2185     };
  2186 
  2187     IntNodeMap *_blossom_index;
  2188     BlossomSet *_blossom_set;
  2189     RangeMap<BlossomData>* _blossom_data;
  2190 
  2191     IntNodeMap *_node_index;
  2192     IntArcMap *_node_heap_index;
  2193 
  2194     struct NodeData {
  2195 
  2196       NodeData(IntArcMap& node_heap_index)
  2197         : heap(node_heap_index) {}
  2198 
  2199       int blossom;
  2200       Value pot;
  2201       BinHeap<Value, IntArcMap> heap;
  2202       std::map<int, Arc> heap_index;
  2203 
  2204       int tree;
  2205     };
  2206 
  2207     RangeMap<NodeData>* _node_data;
  2208 
  2209     typedef ExtendFindEnum<IntIntMap> TreeSet;
  2210 
  2211     IntIntMap *_tree_set_index;
  2212     TreeSet *_tree_set;
  2213 
  2214     IntIntMap *_delta2_index;
  2215     BinHeap<Value, IntIntMap> *_delta2;
  2216 
  2217     IntEdgeMap *_delta3_index;
  2218     BinHeap<Value, IntEdgeMap> *_delta3;
  2219 
  2220     IntIntMap *_delta4_index;
  2221     BinHeap<Value, IntIntMap> *_delta4;
  2222 
  2223     Value _delta_sum;
  2224 
  2225     void createStructures() {
  2226       _node_num = countNodes(_graph);
  2227       _blossom_num = _node_num * 3 / 2;
  2228 
  2229       if (!_matching) {
  2230         _matching = new MatchingMap(_graph);
  2231       }
  2232 
  2233       if (!_node_potential) {
  2234         _node_potential = new NodePotential(_graph);
  2235       }
  2236 
  2237       if (!_blossom_set) {
  2238         _blossom_index = new IntNodeMap(_graph);
  2239         _blossom_set = new BlossomSet(*_blossom_index);
  2240         _blossom_data = new RangeMap<BlossomData>(_blossom_num);
  2241       } else if (_blossom_data->size() != _blossom_num) {
  2242         delete _blossom_data;
  2243         _blossom_data = new RangeMap<BlossomData>(_blossom_num);
  2244       }
  2245 
  2246       if (!_node_index) {
  2247         _node_index = new IntNodeMap(_graph);
  2248         _node_heap_index = new IntArcMap(_graph);
  2249         _node_data = new RangeMap<NodeData>(_node_num,
  2250                                             NodeData(*_node_heap_index));
  2251       } else if (_node_data->size() != _node_num) {
  2252         delete _node_data;
  2253         _node_data = new RangeMap<NodeData>(_node_num,
  2254                                             NodeData(*_node_heap_index));
  2255       }
  2256 
  2257       if (!_tree_set) {
  2258         _tree_set_index = new IntIntMap(_blossom_num);
  2259         _tree_set = new TreeSet(*_tree_set_index);
  2260       } else {
  2261         _tree_set_index->resize(_blossom_num);
  2262       }
  2263 
  2264       if (!_delta2) {
  2265         _delta2_index = new IntIntMap(_blossom_num);
  2266         _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
  2267       } else {
  2268         _delta2_index->resize(_blossom_num);
  2269       }
  2270 
  2271       if (!_delta3) {
  2272         _delta3_index = new IntEdgeMap(_graph);
  2273         _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
  2274       }
  2275 
  2276       if (!_delta4) {
  2277         _delta4_index = new IntIntMap(_blossom_num);
  2278         _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
  2279       } else {
  2280         _delta4_index->resize(_blossom_num);
  2281       }
  2282     }
  2283 
  2284     void destroyStructures() {
  2285       _node_num = countNodes(_graph);
  2286       _blossom_num = _node_num * 3 / 2;
  2287 
  2288       if (_matching) {
  2289         delete _matching;
  2290       }
  2291       if (_node_potential) {
  2292         delete _node_potential;
  2293       }
  2294       if (_blossom_set) {
  2295         delete _blossom_index;
  2296         delete _blossom_set;
  2297         delete _blossom_data;
  2298       }
  2299 
  2300       if (_node_index) {
  2301         delete _node_index;
  2302         delete _node_heap_index;
  2303         delete _node_data;
  2304       }
  2305 
  2306       if (_tree_set) {
  2307         delete _tree_set_index;
  2308         delete _tree_set;
  2309       }
  2310       if (_delta2) {
  2311         delete _delta2_index;
  2312         delete _delta2;
  2313       }
  2314       if (_delta3) {
  2315         delete _delta3_index;
  2316         delete _delta3;
  2317       }
  2318       if (_delta4) {
  2319         delete _delta4_index;
  2320         delete _delta4;
  2321       }
  2322     }
  2323 
  2324     void matchedToEven(int blossom, int tree) {
  2325       if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  2326         _delta2->erase(blossom);
  2327       }
  2328 
  2329       if (!_blossom_set->trivial(blossom)) {
  2330         (*_blossom_data)[blossom].pot -=
  2331           2 * (_delta_sum - (*_blossom_data)[blossom].offset);
  2332       }
  2333 
  2334       for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  2335            n != INVALID; ++n) {
  2336 
  2337         _blossom_set->increase(n, std::numeric_limits<Value>::max());
  2338         int ni = (*_node_index)[n];
  2339 
  2340         (*_node_data)[ni].heap.clear();
  2341         (*_node_data)[ni].heap_index.clear();
  2342 
  2343         (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
  2344 
  2345         for (InArcIt e(_graph, n); e != INVALID; ++e) {
  2346           Node v = _graph.source(e);
  2347           int vb = _blossom_set->find(v);
  2348           int vi = (*_node_index)[v];
  2349 
  2350           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  2351             dualScale * _weight[e];
  2352 
  2353           if ((*_blossom_data)[vb].status == EVEN) {
  2354             if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  2355               _delta3->push(e, rw / 2);
  2356             }
  2357           } else {
  2358             typename std::map<int, Arc>::iterator it =
  2359               (*_node_data)[vi].heap_index.find(tree);
  2360 
  2361             if (it != (*_node_data)[vi].heap_index.end()) {
  2362               if ((*_node_data)[vi].heap[it->second] > rw) {
  2363                 (*_node_data)[vi].heap.replace(it->second, e);
  2364                 (*_node_data)[vi].heap.decrease(e, rw);
  2365                 it->second = e;
  2366               }
  2367             } else {
  2368               (*_node_data)[vi].heap.push(e, rw);
  2369               (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  2370             }
  2371 
  2372             if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  2373               _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  2374 
  2375               if ((*_blossom_data)[vb].status == MATCHED) {
  2376                 if (_delta2->state(vb) != _delta2->IN_HEAP) {
  2377                   _delta2->push(vb, _blossom_set->classPrio(vb) -
  2378                                (*_blossom_data)[vb].offset);
  2379                 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  2380                            (*_blossom_data)[vb].offset){
  2381                   _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  2382                                    (*_blossom_data)[vb].offset);
  2383                 }
  2384               }
  2385             }
  2386           }
  2387         }
  2388       }
  2389       (*_blossom_data)[blossom].offset = 0;
  2390     }
  2391 
  2392     void matchedToOdd(int blossom) {
  2393       if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  2394         _delta2->erase(blossom);
  2395       }
  2396       (*_blossom_data)[blossom].offset += _delta_sum;
  2397       if (!_blossom_set->trivial(blossom)) {
  2398         _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
  2399                      (*_blossom_data)[blossom].offset);
  2400       }
  2401     }
  2402 
  2403     void evenToMatched(int blossom, int tree) {
  2404       if (!_blossom_set->trivial(blossom)) {
  2405         (*_blossom_data)[blossom].pot += 2 * _delta_sum;
  2406       }
  2407 
  2408       for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  2409            n != INVALID; ++n) {
  2410         int ni = (*_node_index)[n];
  2411         (*_node_data)[ni].pot -= _delta_sum;
  2412 
  2413         for (InArcIt e(_graph, n); e != INVALID; ++e) {
  2414           Node v = _graph.source(e);
  2415           int vb = _blossom_set->find(v);
  2416           int vi = (*_node_index)[v];
  2417 
  2418           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  2419             dualScale * _weight[e];
  2420 
  2421           if (vb == blossom) {
  2422             if (_delta3->state(e) == _delta3->IN_HEAP) {
  2423               _delta3->erase(e);
  2424             }
  2425           } else if ((*_blossom_data)[vb].status == EVEN) {
  2426 
  2427             if (_delta3->state(e) == _delta3->IN_HEAP) {
  2428               _delta3->erase(e);
  2429             }
  2430 
  2431             int vt = _tree_set->find(vb);
  2432 
  2433             if (vt != tree) {
  2434 
  2435               Arc r = _graph.oppositeArc(e);
  2436 
  2437               typename std::map<int, Arc>::iterator it =
  2438                 (*_node_data)[ni].heap_index.find(vt);
  2439 
  2440               if (it != (*_node_data)[ni].heap_index.end()) {
  2441                 if ((*_node_data)[ni].heap[it->second] > rw) {
  2442                   (*_node_data)[ni].heap.replace(it->second, r);
  2443                   (*_node_data)[ni].heap.decrease(r, rw);
  2444                   it->second = r;
  2445                 }
  2446               } else {
  2447                 (*_node_data)[ni].heap.push(r, rw);
  2448                 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
  2449               }
  2450 
  2451               if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
  2452                 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
  2453 
  2454                 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
  2455                   _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  2456                                (*_blossom_data)[blossom].offset);
  2457                 } else if ((*_delta2)[blossom] >
  2458                            _blossom_set->classPrio(blossom) -
  2459                            (*_blossom_data)[blossom].offset){
  2460                   _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
  2461                                    (*_blossom_data)[blossom].offset);
  2462                 }
  2463               }
  2464             }
  2465           } else {
  2466 
  2467             typename std::map<int, Arc>::iterator it =
  2468               (*_node_data)[vi].heap_index.find(tree);
  2469 
  2470             if (it != (*_node_data)[vi].heap_index.end()) {
  2471               (*_node_data)[vi].heap.erase(it->second);
  2472               (*_node_data)[vi].heap_index.erase(it);
  2473               if ((*_node_data)[vi].heap.empty()) {
  2474                 _blossom_set->increase(v, std::numeric_limits<Value>::max());
  2475               } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
  2476                 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
  2477               }
  2478 
  2479               if ((*_blossom_data)[vb].status == MATCHED) {
  2480                 if (_blossom_set->classPrio(vb) ==
  2481                     std::numeric_limits<Value>::max()) {
  2482                   _delta2->erase(vb);
  2483                 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
  2484                            (*_blossom_data)[vb].offset) {
  2485                   _delta2->increase(vb, _blossom_set->classPrio(vb) -
  2486                                    (*_blossom_data)[vb].offset);
  2487                 }
  2488               }
  2489             }
  2490           }
  2491         }
  2492       }
  2493     }
  2494 
  2495     void oddToMatched(int blossom) {
  2496       (*_blossom_data)[blossom].offset -= _delta_sum;
  2497 
  2498       if (_blossom_set->classPrio(blossom) !=
  2499           std::numeric_limits<Value>::max()) {
  2500         _delta2->push(blossom, _blossom_set->classPrio(blossom) -
  2501                        (*_blossom_data)[blossom].offset);
  2502       }
  2503 
  2504       if (!_blossom_set->trivial(blossom)) {
  2505         _delta4->erase(blossom);
  2506       }
  2507     }
  2508 
  2509     void oddToEven(int blossom, int tree) {
  2510       if (!_blossom_set->trivial(blossom)) {
  2511         _delta4->erase(blossom);
  2512         (*_blossom_data)[blossom].pot -=
  2513           2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
  2514       }
  2515 
  2516       for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
  2517            n != INVALID; ++n) {
  2518         int ni = (*_node_index)[n];
  2519 
  2520         _blossom_set->increase(n, std::numeric_limits<Value>::max());
  2521 
  2522         (*_node_data)[ni].heap.clear();
  2523         (*_node_data)[ni].heap_index.clear();
  2524         (*_node_data)[ni].pot +=
  2525           2 * _delta_sum - (*_blossom_data)[blossom].offset;
  2526 
  2527         for (InArcIt e(_graph, n); e != INVALID; ++e) {
  2528           Node v = _graph.source(e);
  2529           int vb = _blossom_set->find(v);
  2530           int vi = (*_node_index)[v];
  2531 
  2532           Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
  2533             dualScale * _weight[e];
  2534 
  2535           if ((*_blossom_data)[vb].status == EVEN) {
  2536             if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
  2537               _delta3->push(e, rw / 2);
  2538             }
  2539           } else {
  2540 
  2541             typename std::map<int, Arc>::iterator it =
  2542               (*_node_data)[vi].heap_index.find(tree);
  2543 
  2544             if (it != (*_node_data)[vi].heap_index.end()) {
  2545               if ((*_node_data)[vi].heap[it->second] > rw) {
  2546                 (*_node_data)[vi].heap.replace(it->second, e);
  2547                 (*_node_data)[vi].heap.decrease(e, rw);
  2548                 it->second = e;
  2549               }
  2550             } else {
  2551               (*_node_data)[vi].heap.push(e, rw);
  2552               (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
  2553             }
  2554 
  2555             if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
  2556               _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
  2557 
  2558               if ((*_blossom_data)[vb].status == MATCHED) {
  2559                 if (_delta2->state(vb) != _delta2->IN_HEAP) {
  2560                   _delta2->push(vb, _blossom_set->classPrio(vb) -
  2561                                (*_blossom_data)[vb].offset);
  2562                 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
  2563                            (*_blossom_data)[vb].offset) {
  2564                   _delta2->decrease(vb, _blossom_set->classPrio(vb) -
  2565                                    (*_blossom_data)[vb].offset);
  2566                 }
  2567               }
  2568             }
  2569           }
  2570         }
  2571       }
  2572       (*_blossom_data)[blossom].offset = 0;
  2573     }
  2574 
  2575     void alternatePath(int even, int tree) {
  2576       int odd;
  2577 
  2578       evenToMatched(even, tree);
  2579       (*_blossom_data)[even].status = MATCHED;
  2580 
  2581       while ((*_blossom_data)[even].pred != INVALID) {
  2582         odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
  2583         (*_blossom_data)[odd].status = MATCHED;
  2584         oddToMatched(odd);
  2585         (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
  2586 
  2587         even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
  2588         (*_blossom_data)[even].status = MATCHED;
  2589         evenToMatched(even, tree);
  2590         (*_blossom_data)[even].next =
  2591           _graph.oppositeArc((*_blossom_data)[odd].pred);
  2592       }
  2593 
  2594     }
  2595 
  2596     void destroyTree(int tree) {
  2597       for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
  2598         if ((*_blossom_data)[b].status == EVEN) {
  2599           (*_blossom_data)[b].status = MATCHED;
  2600           evenToMatched(b, tree);
  2601         } else if ((*_blossom_data)[b].status == ODD) {
  2602           (*_blossom_data)[b].status = MATCHED;
  2603           oddToMatched(b);
  2604         }
  2605       }
  2606       _tree_set->eraseClass(tree);
  2607     }
  2608 
  2609     void augmentOnEdge(const Edge& edge) {
  2610 
  2611       int left = _blossom_set->find(_graph.u(edge));
  2612       int right = _blossom_set->find(_graph.v(edge));
  2613 
  2614       int left_tree = _tree_set->find(left);
  2615       alternatePath(left, left_tree);
  2616       destroyTree(left_tree);
  2617 
  2618       int right_tree = _tree_set->find(right);
  2619       alternatePath(right, right_tree);
  2620       destroyTree(right_tree);
  2621 
  2622       (*_blossom_data)[left].next = _graph.direct(edge, true);
  2623       (*_blossom_data)[right].next = _graph.direct(edge, false);
  2624     }
  2625 
  2626     void extendOnArc(const Arc& arc) {
  2627       int base = _blossom_set->find(_graph.target(arc));
  2628       int tree = _tree_set->find(base);
  2629 
  2630       int odd = _blossom_set->find(_graph.source(arc));
  2631       _tree_set->insert(odd, tree);
  2632       (*_blossom_data)[odd].status = ODD;
  2633       matchedToOdd(odd);
  2634       (*_blossom_data)[odd].pred = arc;
  2635 
  2636       int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
  2637       (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
  2638       _tree_set->insert(even, tree);
  2639       (*_blossom_data)[even].status = EVEN;
  2640       matchedToEven(even, tree);
  2641     }
  2642 
  2643     void shrinkOnEdge(const Edge& edge, int tree) {
  2644       int nca = -1;
  2645       std::vector<int> left_path, right_path;
  2646 
  2647       {
  2648         std::set<int> left_set, right_set;
  2649         int left = _blossom_set->find(_graph.u(edge));
  2650         left_path.push_back(left);
  2651         left_set.insert(left);
  2652 
  2653         int right = _blossom_set->find(_graph.v(edge));
  2654         right_path.push_back(right);
  2655         right_set.insert(right);
  2656 
  2657         while (true) {
  2658 
  2659           if ((*_blossom_data)[left].pred == INVALID) break;
  2660 
  2661           left =
  2662             _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  2663           left_path.push_back(left);
  2664           left =
  2665             _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
  2666           left_path.push_back(left);
  2667 
  2668           left_set.insert(left);
  2669 
  2670           if (right_set.find(left) != right_set.end()) {
  2671             nca = left;
  2672             break;
  2673           }
  2674 
  2675           if ((*_blossom_data)[right].pred == INVALID) break;
  2676 
  2677           right =
  2678             _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  2679           right_path.push_back(right);
  2680           right =
  2681             _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
  2682           right_path.push_back(right);
  2683 
  2684           right_set.insert(right);
  2685 
  2686           if (left_set.find(right) != left_set.end()) {
  2687             nca = right;
  2688             break;
  2689           }
  2690 
  2691         }
  2692 
  2693         if (nca == -1) {
  2694           if ((*_blossom_data)[left].pred == INVALID) {
  2695             nca = right;
  2696             while (left_set.find(nca) == left_set.end()) {
  2697               nca =
  2698                 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  2699               right_path.push_back(nca);
  2700               nca =
  2701                 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  2702               right_path.push_back(nca);
  2703             }
  2704           } else {
  2705             nca = left;
  2706             while (right_set.find(nca) == right_set.end()) {
  2707               nca =
  2708                 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  2709               left_path.push_back(nca);
  2710               nca =
  2711                 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
  2712               left_path.push_back(nca);
  2713             }
  2714           }
  2715         }
  2716       }
  2717 
  2718       std::vector<int> subblossoms;
  2719       Arc prev;
  2720 
  2721       prev = _graph.direct(edge, true);
  2722       for (int i = 0; left_path[i] != nca; i += 2) {
  2723         subblossoms.push_back(left_path[i]);
  2724         (*_blossom_data)[left_path[i]].next = prev;
  2725         _tree_set->erase(left_path[i]);
  2726 
  2727         subblossoms.push_back(left_path[i + 1]);
  2728         (*_blossom_data)[left_path[i + 1]].status = EVEN;
  2729         oddToEven(left_path[i + 1], tree);
  2730         _tree_set->erase(left_path[i + 1]);
  2731         prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
  2732       }
  2733 
  2734       int k = 0;
  2735       while (right_path[k] != nca) ++k;
  2736 
  2737       subblossoms.push_back(nca);
  2738       (*_blossom_data)[nca].next = prev;
  2739 
  2740       for (int i = k - 2; i >= 0; i -= 2) {
  2741         subblossoms.push_back(right_path[i + 1]);
  2742         (*_blossom_data)[right_path[i + 1]].status = EVEN;
  2743         oddToEven(right_path[i + 1], tree);
  2744         _tree_set->erase(right_path[i + 1]);
  2745 
  2746         (*_blossom_data)[right_path[i + 1]].next =
  2747           (*_blossom_data)[right_path[i + 1]].pred;
  2748 
  2749         subblossoms.push_back(right_path[i]);
  2750         _tree_set->erase(right_path[i]);
  2751       }
  2752 
  2753       int surface =
  2754         _blossom_set->join(subblossoms.begin(), subblossoms.end());
  2755 
  2756       for (int i = 0; i < int(subblossoms.size()); ++i) {
  2757         if (!_blossom_set->trivial(subblossoms[i])) {
  2758           (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
  2759         }
  2760         (*_blossom_data)[subblossoms[i]].status = MATCHED;
  2761       }
  2762 
  2763       (*_blossom_data)[surface].pot = -2 * _delta_sum;
  2764       (*_blossom_data)[surface].offset = 0;
  2765       (*_blossom_data)[surface].status = EVEN;
  2766       (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
  2767       (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
  2768 
  2769       _tree_set->insert(surface, tree);
  2770       _tree_set->erase(nca);
  2771     }
  2772 
  2773     void splitBlossom(int blossom) {
  2774       Arc next = (*_blossom_data)[blossom].next;
  2775       Arc pred = (*_blossom_data)[blossom].pred;
  2776 
  2777       int tree = _tree_set->find(blossom);
  2778 
  2779       (*_blossom_data)[blossom].status = MATCHED;
  2780       oddToMatched(blossom);
  2781       if (_delta2->state(blossom) == _delta2->IN_HEAP) {
  2782         _delta2->erase(blossom);
  2783       }
  2784 
  2785       std::vector<int> subblossoms;
  2786       _blossom_set->split(blossom, std::back_inserter(subblossoms));
  2787 
  2788       Value offset = (*_blossom_data)[blossom].offset;
  2789       int b = _blossom_set->find(_graph.source(pred));
  2790       int d = _blossom_set->find(_graph.source(next));
  2791 
  2792       int ib = -1, id = -1;
  2793       for (int i = 0; i < int(subblossoms.size()); ++i) {
  2794         if (subblossoms[i] == b) ib = i;
  2795         if (subblossoms[i] == d) id = i;
  2796 
  2797         (*_blossom_data)[subblossoms[i]].offset = offset;
  2798         if (!_blossom_set->trivial(subblossoms[i])) {
  2799           (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
  2800         }
  2801         if (_blossom_set->classPrio(subblossoms[i]) !=
  2802             std::numeric_limits<Value>::max()) {
  2803           _delta2->push(subblossoms[i],
  2804                         _blossom_set->classPrio(subblossoms[i]) -
  2805                         (*_blossom_data)[subblossoms[i]].offset);
  2806         }
  2807       }
  2808 
  2809       if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
  2810         for (int i = (id + 1) % subblossoms.size();
  2811              i != ib; i = (i + 2) % subblossoms.size()) {
  2812           int sb = subblossoms[i];
  2813           int tb = subblossoms[(i + 1) % subblossoms.size()];
  2814           (*_blossom_data)[sb].next =
  2815             _graph.oppositeArc((*_blossom_data)[tb].next);
  2816         }
  2817 
  2818         for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
  2819           int sb = subblossoms[i];
  2820           int tb = subblossoms[(i + 1) % subblossoms.size()];
  2821           int ub = subblossoms[(i + 2) % subblossoms.size()];
  2822 
  2823           (*_blossom_data)[sb].status = ODD;
  2824           matchedToOdd(sb);
  2825           _tree_set->insert(sb, tree);
  2826           (*_blossom_data)[sb].pred = pred;
  2827           (*_blossom_data)[sb].next =
  2828                            _graph.oppositeArc((*_blossom_data)[tb].next);
  2829 
  2830           pred = (*_blossom_data)[ub].next;
  2831 
  2832           (*_blossom_data)[tb].status = EVEN;
  2833           matchedToEven(tb, tree);
  2834           _tree_set->insert(tb, tree);
  2835           (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
  2836         }
  2837 
  2838         (*_blossom_data)[subblossoms[id]].status = ODD;
  2839         matchedToOdd(subblossoms[id]);
  2840         _tree_set->insert(subblossoms[id], tree);
  2841         (*_blossom_data)[subblossoms[id]].next = next;
  2842         (*_blossom_data)[subblossoms[id]].pred = pred;
  2843 
  2844       } else {
  2845 
  2846         for (int i = (ib + 1) % subblossoms.size();
  2847              i != id; i = (i + 2) % subblossoms.size()) {
  2848           int sb = subblossoms[i];
  2849           int tb = subblossoms[(i + 1) % subblossoms.size()];
  2850           (*_blossom_data)[sb].next =
  2851             _graph.oppositeArc((*_blossom_data)[tb].next);
  2852         }
  2853 
  2854         for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
  2855           int sb = subblossoms[i];
  2856           int tb = subblossoms[(i + 1) % subblossoms.size()];
  2857           int ub = subblossoms[(i + 2) % subblossoms.size()];
  2858 
  2859           (*_blossom_data)[sb].status = ODD;
  2860           matchedToOdd(sb);
  2861           _tree_set->insert(sb, tree);
  2862           (*_blossom_data)[sb].next = next;
  2863           (*_blossom_data)[sb].pred =
  2864             _graph.oppositeArc((*_blossom_data)[tb].next);
  2865 
  2866           (*_blossom_data)[tb].status = EVEN;
  2867           matchedToEven(tb, tree);
  2868           _tree_set->insert(tb, tree);
  2869           (*_blossom_data)[tb].pred =
  2870             (*_blossom_data)[tb].next =
  2871             _graph.oppositeArc((*_blossom_data)[ub].next);
  2872           next = (*_blossom_data)[ub].next;
  2873         }
  2874 
  2875         (*_blossom_data)[subblossoms[ib]].status = ODD;
  2876         matchedToOdd(subblossoms[ib]);
  2877         _tree_set->insert(subblossoms[ib], tree);
  2878         (*_blossom_data)[subblossoms[ib]].next = next;
  2879         (*_blossom_data)[subblossoms[ib]].pred = pred;
  2880       }
  2881       _tree_set->erase(blossom);
  2882     }
  2883 
  2884     void extractBlossom(int blossom, const Node& base, const Arc& matching) {
  2885       if (_blossom_set->trivial(blossom)) {
  2886         int bi = (*_node_index)[base];
  2887         Value pot = (*_node_data)[bi].pot;
  2888 
  2889         (*_matching)[base] = matching;
  2890         _blossom_node_list.push_back(base);
  2891         (*_node_potential)[base] = pot;
  2892       } else {
  2893 
  2894         Value pot = (*_blossom_data)[blossom].pot;
  2895         int bn = _blossom_node_list.size();
  2896 
  2897         std::vector<int> subblossoms;
  2898         _blossom_set->split(blossom, std::back_inserter(subblossoms));
  2899         int b = _blossom_set->find(base);
  2900         int ib = -1;
  2901         for (int i = 0; i < int(subblossoms.size()); ++i) {
  2902           if (subblossoms[i] == b) { ib = i; break; }
  2903         }
  2904 
  2905         for (int i = 1; i < int(subblossoms.size()); i += 2) {
  2906           int sb = subblossoms[(ib + i) % subblossoms.size()];
  2907           int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
  2908 
  2909           Arc m = (*_blossom_data)[tb].next;
  2910           extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
  2911           extractBlossom(tb, _graph.source(m), m);
  2912         }
  2913         extractBlossom(subblossoms[ib], base, matching);
  2914 
  2915         int en = _blossom_node_list.size();
  2916 
  2917         _blossom_potential.push_back(BlossomVariable(bn, en, pot));
  2918       }
  2919     }
  2920 
  2921     void extractMatching() {
  2922       std::vector<int> blossoms;
  2923       for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
  2924         blossoms.push_back(c);
  2925       }
  2926 
  2927       for (int i = 0; i < int(blossoms.size()); ++i) {
  2928 
  2929         Value offset = (*_blossom_data)[blossoms[i]].offset;
  2930         (*_blossom_data)[blossoms[i]].pot += 2 * offset;
  2931         for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
  2932              n != INVALID; ++n) {
  2933           (*_node_data)[(*_node_index)[n]].pot -= offset;
  2934         }
  2935 
  2936         Arc matching = (*_blossom_data)[blossoms[i]].next;
  2937         Node base = _graph.source(matching);
  2938         extractBlossom(blossoms[i], base, matching);
  2939       }
  2940     }
  2941 
  2942   public:
  2943 
  2944     /// \brief Constructor
  2945     ///
  2946     /// Constructor.
  2947     MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
  2948       : _graph(graph), _weight(weight), _matching(0),
  2949         _node_potential(0), _blossom_potential(), _blossom_node_list(),
  2950         _node_num(0), _blossom_num(0),
  2951 
  2952         _blossom_index(0), _blossom_set(0), _blossom_data(0),
  2953         _node_index(0), _node_heap_index(0), _node_data(0),
  2954         _tree_set_index(0), _tree_set(0),
  2955 
  2956         _delta2_index(0), _delta2(0),
  2957         _delta3_index(0), _delta3(0),
  2958         _delta4_index(0), _delta4(0),
  2959 
  2960         _delta_sum() {}
  2961 
  2962     ~MaxWeightedPerfectMatching() {
  2963       destroyStructures();
  2964     }
  2965 
  2966     /// \name Execution Control
  2967     /// The simplest way to execute the algorithm is to use the
  2968     /// \ref run() member function.
  2969 
  2970     ///@{
  2971 
  2972     /// \brief Initialize the algorithm
  2973     ///
  2974     /// This function initializes the algorithm.
  2975     void init() {
  2976       createStructures();
  2977 
  2978       _blossom_node_list.clear();
  2979       _blossom_potential.clear();
  2980 
  2981       for (ArcIt e(_graph); e != INVALID; ++e) {
  2982         (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
  2983       }
  2984       for (EdgeIt e(_graph); e != INVALID; ++e) {
  2985         (*_delta3_index)[e] = _delta3->PRE_HEAP;
  2986       }
  2987       for (int i = 0; i < _blossom_num; ++i) {
  2988         (*_delta2_index)[i] = _delta2->PRE_HEAP;
  2989         (*_delta4_index)[i] = _delta4->PRE_HEAP;
  2990       }
  2991 
  2992       _delta2->clear();
  2993       _delta3->clear();
  2994       _delta4->clear();
  2995       _blossom_set->clear();
  2996       _tree_set->clear();
  2997 
  2998       int index = 0;
  2999       for (NodeIt n(_graph); n != INVALID; ++n) {
  3000         Value max = - std::numeric_limits<Value>::max();
  3001         for (OutArcIt e(_graph, n); e != INVALID; ++e) {
  3002           if (_graph.target(e) == n) continue;
  3003           if ((dualScale * _weight[e]) / 2 > max) {
  3004             max = (dualScale * _weight[e]) / 2;
  3005           }
  3006         }
  3007         (*_node_index)[n] = index;
  3008         (*_node_data)[index].heap_index.clear();
  3009         (*_node_data)[index].heap.clear();
  3010         (*_node_data)[index].pot = max;
  3011         int blossom =
  3012           _blossom_set->insert(n, std::numeric_limits<Value>::max());
  3013 
  3014         _tree_set->insert(blossom);
  3015 
  3016         (*_blossom_data)[blossom].status = EVEN;
  3017         (*_blossom_data)[blossom].pred = INVALID;
  3018         (*_blossom_data)[blossom].next = INVALID;
  3019         (*_blossom_data)[blossom].pot = 0;
  3020         (*_blossom_data)[blossom].offset = 0;
  3021         ++index;
  3022       }
  3023       for (EdgeIt e(_graph); e != INVALID; ++e) {
  3024         int si = (*_node_index)[_graph.u(e)];
  3025         int ti = (*_node_index)[_graph.v(e)];
  3026         if (_graph.u(e) != _graph.v(e)) {
  3027           _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
  3028                             dualScale * _weight[e]) / 2);
  3029         }
  3030       }
  3031     }
  3032 
  3033     /// \brief Start the algorithm
  3034     ///
  3035     /// This function starts the algorithm.
  3036     ///
  3037     /// \pre \ref init() must be called before using this function.
  3038     bool start() {
  3039       enum OpType {
  3040         D2, D3, D4
  3041       };
  3042 
  3043       int unmatched = _node_num;
  3044       while (unmatched > 0) {
  3045         Value d2 = !_delta2->empty() ?
  3046           _delta2->prio() : std::numeric_limits<Value>::max();
  3047 
  3048         Value d3 = !_delta3->empty() ?
  3049           _delta3->prio() : std::numeric_limits<Value>::max();
  3050 
  3051         Value d4 = !_delta4->empty() ?
  3052           _delta4->prio() : std::numeric_limits<Value>::max();
  3053 
  3054         _delta_sum = d2; OpType ot = D2;
  3055         if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
  3056         if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
  3057 
  3058         if (_delta_sum == std::numeric_limits<Value>::max()) {
  3059           return false;
  3060         }
  3061 
  3062         switch (ot) {
  3063         case D2:
  3064           {
  3065             int blossom = _delta2->top();
  3066             Node n = _blossom_set->classTop(blossom);
  3067             Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
  3068             extendOnArc(e);
  3069           }
  3070           break;
  3071         case D3:
  3072           {
  3073             Edge e = _delta3->top();
  3074 
  3075             int left_blossom = _blossom_set->find(_graph.u(e));
  3076             int right_blossom = _blossom_set->find(_graph.v(e));
  3077 
  3078             if (left_blossom == right_blossom) {
  3079               _delta3->pop();
  3080             } else {
  3081               int left_tree = _tree_set->find(left_blossom);
  3082               int right_tree = _tree_set->find(right_blossom);
  3083 
  3084               if (left_tree == right_tree) {
  3085                 shrinkOnEdge(e, left_tree);
  3086               } else {
  3087                 augmentOnEdge(e);
  3088                 unmatched -= 2;
  3089               }
  3090             }
  3091           } break;
  3092         case D4:
  3093           splitBlossom(_delta4->top());
  3094           break;
  3095         }
  3096       }
  3097       extractMatching();
  3098       return true;
  3099     }
  3100 
  3101     /// \brief Run the algorithm.
  3102     ///
  3103     /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
  3104     ///
  3105     /// \note mwpm.run() is just a shortcut of the following code.
  3106     /// \code
  3107     ///   mwpm.init();
  3108     ///   mwpm.start();
  3109     /// \endcode
  3110     bool run() {
  3111       init();
  3112       return start();
  3113     }
  3114 
  3115     /// @}
  3116 
  3117     /// \name Primal Solution
  3118     /// Functions to get the primal solution, i.e. the maximum weighted 
  3119     /// perfect matching.\n
  3120     /// Either \ref run() or \ref start() function should be called before
  3121     /// using them.
  3122 
  3123     /// @{
  3124 
  3125     /// \brief Return the weight of the matching.
  3126     ///
  3127     /// This function returns the weight of the found matching.
  3128     ///
  3129     /// \pre Either run() or start() must be called before using this function.
  3130     Value matchingWeight() const {
  3131       Value sum = 0;
  3132       for (NodeIt n(_graph); n != INVALID; ++n) {
  3133         if ((*_matching)[n] != INVALID) {
  3134           sum += _weight[(*_matching)[n]];
  3135         }
  3136       }
  3137       return sum /= 2;
  3138     }
  3139 
  3140     /// \brief Return \c true if the given edge is in the matching.
  3141     ///
  3142     /// This function returns \c true if the given edge is in the found 
  3143     /// matching.
  3144     ///
  3145     /// \pre Either run() or start() must be called before using this function.
  3146     bool matching(const Edge& edge) const {
  3147       return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
  3148     }
  3149 
  3150     /// \brief Return the matching arc (or edge) incident to the given node.
  3151     ///
  3152     /// This function returns the matching arc (or edge) incident to the
  3153     /// given node in the found matching or \c INVALID if the node is 
  3154     /// not covered by the matching.
  3155     ///
  3156     /// \pre Either run() or start() must be called before using this function.
  3157     Arc matching(const Node& node) const {
  3158       return (*_matching)[node];
  3159     }
  3160 
  3161     /// \brief Return a const reference to the matching map.
  3162     ///
  3163     /// This function returns a const reference to a node map that stores
  3164     /// the matching arc (or edge) incident to each node.
  3165     const MatchingMap& matchingMap() const {
  3166       return *_matching;
  3167     }
  3168 
  3169     /// \brief Return the mate of the given node.
  3170     ///
  3171     /// This function returns the mate of the given node in the found 
  3172     /// matching or \c INVALID if the node is not covered by the matching.
  3173     ///
  3174     /// \pre Either run() or start() must be called before using this function.
  3175     Node mate(const Node& node) const {
  3176       return _graph.target((*_matching)[node]);
  3177     }
  3178 
  3179     /// @}
  3180 
  3181     /// \name Dual Solution
  3182     /// Functions to get the dual solution.\n
  3183     /// Either \ref run() or \ref start() function should be called before
  3184     /// using them.
  3185 
  3186     /// @{
  3187 
  3188     /// \brief Return the value of the dual solution.
  3189     ///
  3190     /// This function returns the value of the dual solution. 
  3191     /// It should be equal to the primal value scaled by \ref dualScale 
  3192     /// "dual scale".
  3193     ///
  3194     /// \pre Either run() or start() must be called before using this function.
  3195     Value dualValue() const {
  3196       Value sum = 0;
  3197       for (NodeIt n(_graph); n != INVALID; ++n) {
  3198         sum += nodeValue(n);
  3199       }
  3200       for (int i = 0; i < blossomNum(); ++i) {
  3201         sum += blossomValue(i) * (blossomSize(i) / 2);
  3202       }
  3203       return sum;
  3204     }
  3205 
  3206     /// \brief Return the dual value (potential) of the given node.
  3207     ///
  3208     /// This function returns the dual value (potential) of the given node.
  3209     ///
  3210     /// \pre Either run() or start() must be called before using this function.
  3211     Value nodeValue(const Node& n) const {
  3212       return (*_node_potential)[n];
  3213     }
  3214 
  3215     /// \brief Return the number of the blossoms in the basis.
  3216     ///
  3217     /// This function returns the number of the blossoms in the basis.
  3218     ///
  3219     /// \pre Either run() or start() must be called before using this function.
  3220     /// \see BlossomIt
  3221     int blossomNum() const {
  3222       return _blossom_potential.size();
  3223     }
  3224 
  3225     /// \brief Return the number of the nodes in the given blossom.
  3226     ///
  3227     /// This function returns the number of the nodes in the given blossom.
  3228     ///
  3229     /// \pre Either run() or start() must be called before using this function.
  3230     /// \see BlossomIt
  3231     int blossomSize(int k) const {
  3232       return _blossom_potential[k].end - _blossom_potential[k].begin;
  3233     }
  3234 
  3235     /// \brief Return the dual value (ptential) of the given blossom.
  3236     ///
  3237     /// This function returns the dual value (ptential) of the given blossom.
  3238     ///
  3239     /// \pre Either run() or start() must be called before using this function.
  3240     Value blossomValue(int k) const {
  3241       return _blossom_potential[k].value;
  3242     }
  3243 
  3244     /// \brief Iterator for obtaining the nodes of a blossom.
  3245     ///
  3246     /// This class provides an iterator for obtaining the nodes of the 
  3247     /// given blossom. It lists a subset of the nodes.
  3248     /// Before using this iterator, you must allocate a 
  3249     /// MaxWeightedPerfectMatching class and execute it.
  3250     class BlossomIt {
  3251     public:
  3252 
  3253       /// \brief Constructor.
  3254       ///
  3255       /// Constructor to get the nodes of the given variable.
  3256       ///
  3257       /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()" 
  3258       /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()" 
  3259       /// must be called before initializing this iterator.
  3260       BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
  3261         : _algorithm(&algorithm)
  3262       {
  3263         _index = _algorithm->_blossom_potential[variable].begin;
  3264         _last = _algorithm->_blossom_potential[variable].end;
  3265       }
  3266 
  3267       /// \brief Conversion to \c Node.
  3268       ///
  3269       /// Conversion to \c Node.
  3270       operator Node() const {
  3271         return _algorithm->_blossom_node_list[_index];
  3272       }
  3273 
  3274       /// \brief Increment operator.
  3275       ///
  3276       /// Increment operator.
  3277       BlossomIt& operator++() {
  3278         ++_index;
  3279         return *this;
  3280       }
  3281 
  3282       /// \brief Validity checking
  3283       ///
  3284       /// This function checks whether the iterator is invalid.
  3285       bool operator==(Invalid) const { return _index == _last; }
  3286 
  3287       /// \brief Validity checking
  3288       ///
  3289       /// This function checks whether the iterator is valid.
  3290       bool operator!=(Invalid) const { return _index != _last; }
  3291 
  3292     private:
  3293       const MaxWeightedPerfectMatching* _algorithm;
  3294       int _last;
  3295       int _index;
  3296     };
  3297 
  3298     /// @}
  3299 
  3300   };
  3301 
  3302 } //END OF NAMESPACE LEMON
  3303 
  3304 #endif //LEMON_MAX_MATCHING_H