COIN-OR::LEMON - Graph Library

source: lemon-1.2/lemon/matching.h @ 872:41d7ac528c3a

Last change on this file since 872:41d7ac528c3a was 870:61120524af27, checked in by Balazs Dezso <deba@…>, 15 years ago

Fractional matching initialization of weighted matchings (#314)

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