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