1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2011
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_MAX_MATCHING_H
20 #define LEMON_MAX_MATCHING_H
27 #include <lemon/core.h>
28 #include <lemon/unionfind.h>
29 #include <lemon/bin_heap.h>
30 #include <lemon/maps.h>
34 ///\brief Maximum matching algorithms in general graphs.
40 /// \brief Maximum cardinality matching in general graphs
42 /// This class implements Edmonds' alternating forest matching algorithm
43 /// for finding a maximum cardinality matching in a general undirected graph.
44 /// It can be started from an arbitrary initial matching
45 /// (the default is the empty one).
47 /// The dual solution of the problem is a map of the nodes to
48 /// \ref MaxMatching::Status "Status", having values \c EVEN (or \c D),
49 /// \c ODD (or \c A) and \c MATCHED (or \c C) defining the Gallai-Edmonds
50 /// decomposition of the graph. The nodes in \c EVEN/D induce a subgraph
51 /// with factor-critical components, the nodes in \c ODD/A form the
52 /// canonical barrier, and the nodes in \c MATCHED/C induce a graph having
53 /// a perfect matching. The number of the factor-critical components
54 /// minus the number of barrier nodes is a lower bound on the
55 /// unmatched nodes, and the matching is optimal if and only if this bound is
56 /// tight. This decomposition can be obtained using \ref status() or
57 /// \ref statusMap() after running the algorithm.
59 /// \tparam GR The undirected graph type the algorithm runs on.
60 template <typename GR>
64 /// The graph type of the algorithm
66 /// The type of the matching map
67 typedef typename Graph::template NodeMap<typename Graph::Arc>
70 ///\brief Status constants for Gallai-Edmonds decomposition.
72 ///These constants are used for indicating the Gallai-Edmonds
73 ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
74 ///induce a subgraph with factor-critical components, the nodes with
75 ///status \c ODD (or \c A) form the canonical barrier, and the nodes
76 ///with status \c MATCHED (or \c C) induce a subgraph having a
79 EVEN = 1, ///< = 1. (\c D is an alias for \c EVEN.)
81 MATCHED = 0, ///< = 0. (\c C is an alias for \c MATCHED.)
83 ODD = -1, ///< = -1. (\c A is an alias for \c ODD.)
85 UNMATCHED = -2 ///< = -2.
88 /// The type of the status map
89 typedef typename Graph::template NodeMap<Status> StatusMap;
93 TEMPLATE_GRAPH_TYPEDEFS(Graph);
95 typedef UnionFindEnum<IntNodeMap> BlossomSet;
96 typedef ExtendFindEnum<IntNodeMap> TreeSet;
97 typedef RangeMap<Node> NodeIntMap;
98 typedef MatchingMap EarMap;
99 typedef std::vector<Node> NodeQueue;
102 MatchingMap* _matching;
107 IntNodeMap* _blossom_set_index;
108 BlossomSet* _blossom_set;
109 NodeIntMap* _blossom_rep;
111 IntNodeMap* _tree_set_index;
114 NodeQueue _node_queue;
115 int _process, _postpone, _last;
121 void createStructures() {
122 _node_num = countNodes(_graph);
124 _matching = new MatchingMap(_graph);
127 _status = new StatusMap(_graph);
130 _ear = new EarMap(_graph);
133 _blossom_set_index = new IntNodeMap(_graph);
134 _blossom_set = new BlossomSet(*_blossom_set_index);
137 _blossom_rep = new NodeIntMap(_node_num);
140 _tree_set_index = new IntNodeMap(_graph);
141 _tree_set = new TreeSet(*_tree_set_index);
143 _node_queue.resize(_node_num);
146 void destroyStructures() {
158 delete _blossom_set_index;
164 delete _tree_set_index;
169 void processDense(const Node& n) {
170 _process = _postpone = _last = 0;
171 _node_queue[_last++] = n;
173 while (_process != _last) {
174 Node u = _node_queue[_process++];
175 for (OutArcIt a(_graph, u); a != INVALID; ++a) {
176 Node v = _graph.target(a);
177 if ((*_status)[v] == MATCHED) {
179 } else if ((*_status)[v] == UNMATCHED) {
186 while (_postpone != _last) {
187 Node u = _node_queue[_postpone++];
189 for (OutArcIt a(_graph, u); a != INVALID ; ++a) {
190 Node v = _graph.target(a);
192 if ((*_status)[v] == EVEN) {
193 if (_blossom_set->find(u) != _blossom_set->find(v)) {
198 while (_process != _last) {
199 Node w = _node_queue[_process++];
200 for (OutArcIt b(_graph, w); b != INVALID; ++b) {
201 Node x = _graph.target(b);
202 if ((*_status)[x] == MATCHED) {
204 } else if ((*_status)[x] == UNMATCHED) {
214 void processSparse(const Node& n) {
215 _process = _last = 0;
216 _node_queue[_last++] = n;
217 while (_process != _last) {
218 Node u = _node_queue[_process++];
219 for (OutArcIt a(_graph, u); a != INVALID; ++a) {
220 Node v = _graph.target(a);
222 if ((*_status)[v] == EVEN) {
223 if (_blossom_set->find(u) != _blossom_set->find(v)) {
226 } else if ((*_status)[v] == MATCHED) {
228 } else if ((*_status)[v] == UNMATCHED) {
236 void shrinkOnEdge(const Edge& e) {
240 std::set<Node> left_set, right_set;
242 Node left = (*_blossom_rep)[_blossom_set->find(_graph.u(e))];
243 left_set.insert(left);
245 Node right = (*_blossom_rep)[_blossom_set->find(_graph.v(e))];
246 right_set.insert(right);
249 if ((*_matching)[left] == INVALID) break;
250 left = _graph.target((*_matching)[left]);
251 left = (*_blossom_rep)[_blossom_set->
252 find(_graph.target((*_ear)[left]))];
253 if (right_set.find(left) != right_set.end()) {
257 left_set.insert(left);
259 if ((*_matching)[right] == INVALID) break;
260 right = _graph.target((*_matching)[right]);
261 right = (*_blossom_rep)[_blossom_set->
262 find(_graph.target((*_ear)[right]))];
263 if (left_set.find(right) != left_set.end()) {
267 right_set.insert(right);
270 if (nca == INVALID) {
271 if ((*_matching)[left] == INVALID) {
273 while (left_set.find(nca) == left_set.end()) {
274 nca = _graph.target((*_matching)[nca]);
275 nca =(*_blossom_rep)[_blossom_set->
276 find(_graph.target((*_ear)[nca]))];
280 while (right_set.find(nca) == right_set.end()) {
281 nca = _graph.target((*_matching)[nca]);
282 nca = (*_blossom_rep)[_blossom_set->
283 find(_graph.target((*_ear)[nca]))];
291 Node node = _graph.u(e);
292 Arc arc = _graph.direct(e, true);
293 Node base = (*_blossom_rep)[_blossom_set->find(node)];
295 while (base != nca) {
300 n = _graph.target((*_matching)[n]);
302 n = _graph.target(a);
303 (*_ear)[n] = _graph.oppositeArc(a);
305 node = _graph.target((*_matching)[base]);
306 _tree_set->erase(base);
307 _tree_set->erase(node);
308 _blossom_set->insert(node, _blossom_set->find(base));
309 (*_status)[node] = EVEN;
310 _node_queue[_last++] = node;
311 arc = _graph.oppositeArc((*_ear)[node]);
312 node = _graph.target((*_ear)[node]);
313 base = (*_blossom_rep)[_blossom_set->find(node)];
314 _blossom_set->join(_graph.target(arc), base);
318 (*_blossom_rep)[_blossom_set->find(nca)] = nca;
322 Node node = _graph.v(e);
323 Arc arc = _graph.direct(e, false);
324 Node base = (*_blossom_rep)[_blossom_set->find(node)];
326 while (base != nca) {
331 n = _graph.target((*_matching)[n]);
333 n = _graph.target(a);
334 (*_ear)[n] = _graph.oppositeArc(a);
336 node = _graph.target((*_matching)[base]);
337 _tree_set->erase(base);
338 _tree_set->erase(node);
339 _blossom_set->insert(node, _blossom_set->find(base));
340 (*_status)[node] = EVEN;
341 _node_queue[_last++] = node;
342 arc = _graph.oppositeArc((*_ear)[node]);
343 node = _graph.target((*_ear)[node]);
344 base = (*_blossom_rep)[_blossom_set->find(node)];
345 _blossom_set->join(_graph.target(arc), base);
349 (*_blossom_rep)[_blossom_set->find(nca)] = nca;
352 void extendOnArc(const Arc& a) {
353 Node base = _graph.source(a);
354 Node odd = _graph.target(a);
356 (*_ear)[odd] = _graph.oppositeArc(a);
357 Node even = _graph.target((*_matching)[odd]);
358 (*_blossom_rep)[_blossom_set->insert(even)] = even;
359 (*_status)[odd] = ODD;
360 (*_status)[even] = EVEN;
361 int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(base)]);
362 _tree_set->insert(odd, tree);
363 _tree_set->insert(even, tree);
364 _node_queue[_last++] = even;
368 void augmentOnArc(const Arc& a) {
369 Node even = _graph.source(a);
370 Node odd = _graph.target(a);
372 int tree = _tree_set->find((*_blossom_rep)[_blossom_set->find(even)]);
374 (*_matching)[odd] = _graph.oppositeArc(a);
375 (*_status)[odd] = MATCHED;
377 Arc arc = (*_matching)[even];
378 (*_matching)[even] = a;
380 while (arc != INVALID) {
381 odd = _graph.target(arc);
383 even = _graph.target(arc);
384 (*_matching)[odd] = arc;
385 arc = (*_matching)[even];
386 (*_matching)[even] = _graph.oppositeArc((*_matching)[odd]);
389 for (typename TreeSet::ItemIt it(*_tree_set, tree);
390 it != INVALID; ++it) {
391 if ((*_status)[it] == ODD) {
392 (*_status)[it] = MATCHED;
394 int blossom = _blossom_set->find(it);
395 for (typename BlossomSet::ItemIt jt(*_blossom_set, blossom);
396 jt != INVALID; ++jt) {
397 (*_status)[jt] = MATCHED;
399 _blossom_set->eraseClass(blossom);
402 _tree_set->eraseClass(tree);
408 /// \brief Constructor
411 MaxMatching(const Graph& graph)
412 : _graph(graph), _matching(0), _status(0), _ear(0),
413 _blossom_set_index(0), _blossom_set(0), _blossom_rep(0),
414 _tree_set_index(0), _tree_set(0) {}
420 /// \name Execution Control
421 /// The simplest way to execute the algorithm is to use the
422 /// \c run() member function.\n
423 /// If you need better control on the execution, you have to call
424 /// one of the functions \ref init(), \ref greedyInit() or
425 /// \ref matchingInit() first, then you can start the algorithm with
426 /// \ref startSparse() or \ref startDense().
430 /// \brief Set the initial matching to the empty matching.
432 /// This function sets the initial matching to the empty matching.
435 for(NodeIt n(_graph); n != INVALID; ++n) {
436 (*_matching)[n] = INVALID;
437 (*_status)[n] = UNMATCHED;
441 /// \brief Find an initial matching in a greedy way.
443 /// This function finds an initial matching in a greedy way.
446 for (NodeIt n(_graph); n != INVALID; ++n) {
447 (*_matching)[n] = INVALID;
448 (*_status)[n] = UNMATCHED;
450 for (NodeIt n(_graph); n != INVALID; ++n) {
451 if ((*_matching)[n] == INVALID) {
452 for (OutArcIt a(_graph, n); a != INVALID ; ++a) {
453 Node v = _graph.target(a);
454 if ((*_matching)[v] == INVALID && v != n) {
456 (*_status)[n] = MATCHED;
457 (*_matching)[v] = _graph.oppositeArc(a);
458 (*_status)[v] = MATCHED;
467 /// \brief Initialize the matching from a map.
469 /// This function initializes the matching from a \c bool valued edge
470 /// map. This map should have the property that there are no two incident
471 /// edges with \c true value, i.e. it really contains a matching.
472 /// \return \c true if the map contains a matching.
473 template <typename MatchingMap>
474 bool matchingInit(const MatchingMap& matching) {
477 for (NodeIt n(_graph); n != INVALID; ++n) {
478 (*_matching)[n] = INVALID;
479 (*_status)[n] = UNMATCHED;
481 for(EdgeIt e(_graph); e!=INVALID; ++e) {
484 Node u = _graph.u(e);
485 if ((*_matching)[u] != INVALID) return false;
486 (*_matching)[u] = _graph.direct(e, true);
487 (*_status)[u] = MATCHED;
489 Node v = _graph.v(e);
490 if ((*_matching)[v] != INVALID) return false;
491 (*_matching)[v] = _graph.direct(e, false);
492 (*_status)[v] = MATCHED;
498 /// \brief Start Edmonds' algorithm
500 /// This function runs the original Edmonds' algorithm.
502 /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
503 /// called before using this function.
505 for(NodeIt n(_graph); n != INVALID; ++n) {
506 if ((*_status)[n] == UNMATCHED) {
507 (*_blossom_rep)[_blossom_set->insert(n)] = n;
508 _tree_set->insert(n);
509 (*_status)[n] = EVEN;
515 /// \brief Start Edmonds' algorithm with a heuristic improvement
518 /// This function runs Edmonds' algorithm with a heuristic of postponing
519 /// shrinks, therefore resulting in a faster algorithm for dense graphs.
521 /// \pre \ref init(), \ref greedyInit() or \ref matchingInit() must be
522 /// called before using this function.
524 for(NodeIt n(_graph); n != INVALID; ++n) {
525 if ((*_status)[n] == UNMATCHED) {
526 (*_blossom_rep)[_blossom_set->insert(n)] = n;
527 _tree_set->insert(n);
528 (*_status)[n] = EVEN;
535 /// \brief Run Edmonds' algorithm
537 /// This function runs Edmonds' algorithm. An additional heuristic of
538 /// postponing shrinks is used for relatively dense graphs
539 /// (for which <tt>m>=2*n</tt> holds).
541 if (countEdges(_graph) < 2 * countNodes(_graph)) {
552 /// \name Primal Solution
553 /// Functions to get the primal solution, i.e. the maximum matching.
557 /// \brief Return the size (cardinality) of the matching.
559 /// This function returns the size (cardinality) of the current matching.
560 /// After run() it returns the size of the maximum matching in the graph.
561 int matchingSize() const {
563 for (NodeIt n(_graph); n != INVALID; ++n) {
564 if ((*_matching)[n] != INVALID) {
571 /// \brief Return \c true if the given edge is in the matching.
573 /// This function returns \c true if the given edge is in the current
575 bool matching(const Edge& edge) const {
576 return edge == (*_matching)[_graph.u(edge)];
579 /// \brief Return the matching arc (or edge) incident to the given node.
581 /// This function returns the matching arc (or edge) incident to the
582 /// given node in the current matching or \c INVALID if the node is
583 /// not covered by the matching.
584 Arc matching(const Node& n) const {
585 return (*_matching)[n];
588 /// \brief Return a const reference to the matching map.
590 /// This function returns a const reference to a node map that stores
591 /// the matching arc (or edge) incident to each node.
592 const MatchingMap& matchingMap() const {
596 /// \brief Return the mate of the given node.
598 /// This function returns the mate of the given node in the current
599 /// matching or \c INVALID if the node is not covered by the matching.
600 Node mate(const Node& n) const {
601 return (*_matching)[n] != INVALID ?
602 _graph.target((*_matching)[n]) : INVALID;
607 /// \name Dual Solution
608 /// Functions to get the dual solution, i.e. the Gallai-Edmonds
613 /// \brief Return the status of the given node in the Edmonds-Gallai
616 /// This function returns the \ref Status "status" of the given node
617 /// in the Edmonds-Gallai decomposition.
618 Status status(const Node& n) const {
619 return (*_status)[n];
622 /// \brief Return a const reference to the status map, which stores
623 /// the Edmonds-Gallai decomposition.
625 /// This function returns a const reference to a node map that stores the
626 /// \ref Status "status" of each node in the Edmonds-Gallai decomposition.
627 const StatusMap& statusMap() const {
631 /// \brief Return \c true if the given node is in the barrier.
633 /// This function returns \c true if the given node is in the barrier.
634 bool barrier(const Node& n) const {
635 return (*_status)[n] == ODD;
642 /// \ingroup matching
644 /// \brief Weighted matching in general graphs
646 /// This class provides an efficient implementation of Edmond's
647 /// maximum weighted matching algorithm. The implementation is based
648 /// on extensive use of priority queues and provides
649 /// \f$O(nm\log n)\f$ time complexity.
651 /// The maximum weighted matching problem is to find a subset of the
652 /// edges in an undirected graph with maximum overall weight for which
653 /// each node has at most one incident edge.
654 /// It can be formulated with the following linear program.
655 /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
656 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
657 \quad \forall B\in\mathcal{O}\f] */
658 /// \f[x_e \ge 0\quad \forall e\in E\f]
659 /// \f[\max \sum_{e\in E}x_ew_e\f]
660 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
661 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
662 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
663 /// subsets of the nodes.
665 /// The algorithm calculates an optimal matching and a proof of the
666 /// optimality. The solution of the dual problem can be used to check
667 /// the result of the algorithm. The dual linear problem is the
669 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}
670 z_B \ge w_{uv} \quad \forall uv\in E\f] */
671 /// \f[y_u \ge 0 \quad \forall u \in V\f]
672 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
673 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
674 \frac{\vert B \vert - 1}{2}z_B\f] */
676 /// The algorithm can be executed with the run() function.
677 /// After it the matching (the primal solution) and the dual solution
678 /// can be obtained using the query functions and the
679 /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
680 /// which is able to iterate on the nodes of a blossom.
681 /// If the value type is integer, then the dual solution is multiplied
682 /// by \ref MaxWeightedMatching::dualScale "4".
684 /// \tparam GR The undirected graph type the algorithm runs on.
685 /// \tparam WM The type edge weight map. The default type is
686 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
688 template <typename GR, typename WM>
690 template <typename GR,
691 typename WM = typename GR::template EdgeMap<int> >
693 class MaxWeightedMatching {
696 /// The graph type of the algorithm
698 /// The type of the edge weight map
699 typedef WM WeightMap;
700 /// The value type of the edge weights
701 typedef typename WeightMap::Value Value;
703 /// The type of the matching map
704 typedef typename Graph::template NodeMap<typename Graph::Arc>
707 /// \brief Scaling factor for dual solution
709 /// Scaling factor for dual solution. It is equal to 4 or 1
710 /// according to the value type.
711 static const int dualScale =
712 std::numeric_limits<Value>::is_integer ? 4 : 1;
716 TEMPLATE_GRAPH_TYPEDEFS(Graph);
718 typedef typename Graph::template NodeMap<Value> NodePotential;
719 typedef std::vector<Node> BlossomNodeList;
721 struct BlossomVariable {
725 BlossomVariable(int _begin, int _end, Value _value)
726 : begin(_begin), end(_end), value(_value) {}
730 typedef std::vector<BlossomVariable> BlossomPotential;
733 const WeightMap& _weight;
735 MatchingMap* _matching;
737 NodePotential* _node_potential;
739 BlossomPotential _blossom_potential;
740 BlossomNodeList _blossom_node_list;
745 typedef RangeMap<int> IntIntMap;
748 EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
751 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
760 IntNodeMap *_blossom_index;
761 BlossomSet *_blossom_set;
762 RangeMap<BlossomData>* _blossom_data;
764 IntNodeMap *_node_index;
765 IntArcMap *_node_heap_index;
769 NodeData(IntArcMap& node_heap_index)
770 : heap(node_heap_index) {}
774 BinHeap<Value, IntArcMap> heap;
775 std::map<int, Arc> heap_index;
780 RangeMap<NodeData>* _node_data;
782 typedef ExtendFindEnum<IntIntMap> TreeSet;
784 IntIntMap *_tree_set_index;
787 IntNodeMap *_delta1_index;
788 BinHeap<Value, IntNodeMap> *_delta1;
790 IntIntMap *_delta2_index;
791 BinHeap<Value, IntIntMap> *_delta2;
793 IntEdgeMap *_delta3_index;
794 BinHeap<Value, IntEdgeMap> *_delta3;
796 IntIntMap *_delta4_index;
797 BinHeap<Value, IntIntMap> *_delta4;
801 void createStructures() {
802 _node_num = countNodes(_graph);
803 _blossom_num = _node_num * 3 / 2;
806 _matching = new MatchingMap(_graph);
809 if (!_node_potential) {
810 _node_potential = new NodePotential(_graph);
814 _blossom_index = new IntNodeMap(_graph);
815 _blossom_set = new BlossomSet(*_blossom_index);
816 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
817 } else if (_blossom_data->size() != _blossom_num) {
818 delete _blossom_data;
819 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
823 _node_index = new IntNodeMap(_graph);
824 _node_heap_index = new IntArcMap(_graph);
825 _node_data = new RangeMap<NodeData>(_node_num,
826 NodeData(*_node_heap_index));
829 _node_data = new RangeMap<NodeData>(_node_num,
830 NodeData(*_node_heap_index));
834 _tree_set_index = new IntIntMap(_blossom_num);
835 _tree_set = new TreeSet(*_tree_set_index);
837 _tree_set_index->resize(_blossom_num);
841 _delta1_index = new IntNodeMap(_graph);
842 _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
846 _delta2_index = new IntIntMap(_blossom_num);
847 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
849 _delta2_index->resize(_blossom_num);
853 _delta3_index = new IntEdgeMap(_graph);
854 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
858 _delta4_index = new IntIntMap(_blossom_num);
859 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
861 _delta4_index->resize(_blossom_num);
865 void destroyStructures() {
866 _node_num = countNodes(_graph);
867 _blossom_num = _node_num * 3 / 2;
872 if (_node_potential) {
873 delete _node_potential;
876 delete _blossom_index;
878 delete _blossom_data;
883 delete _node_heap_index;
888 delete _tree_set_index;
892 delete _delta1_index;
896 delete _delta2_index;
900 delete _delta3_index;
904 delete _delta4_index;
909 void matchedToEven(int blossom, int tree) {
910 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
911 _delta2->erase(blossom);
914 if (!_blossom_set->trivial(blossom)) {
915 (*_blossom_data)[blossom].pot -=
916 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
919 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
922 _blossom_set->increase(n, std::numeric_limits<Value>::max());
923 int ni = (*_node_index)[n];
925 (*_node_data)[ni].heap.clear();
926 (*_node_data)[ni].heap_index.clear();
928 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
930 _delta1->push(n, (*_node_data)[ni].pot);
932 for (InArcIt e(_graph, n); e != INVALID; ++e) {
933 Node v = _graph.source(e);
934 int vb = _blossom_set->find(v);
935 int vi = (*_node_index)[v];
937 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
938 dualScale * _weight[e];
940 if ((*_blossom_data)[vb].status == EVEN) {
941 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
942 _delta3->push(e, rw / 2);
944 } else if ((*_blossom_data)[vb].status == UNMATCHED) {
945 if (_delta3->state(e) != _delta3->IN_HEAP) {
946 _delta3->push(e, rw);
949 typename std::map<int, Arc>::iterator it =
950 (*_node_data)[vi].heap_index.find(tree);
952 if (it != (*_node_data)[vi].heap_index.end()) {
953 if ((*_node_data)[vi].heap[it->second] > rw) {
954 (*_node_data)[vi].heap.replace(it->second, e);
955 (*_node_data)[vi].heap.decrease(e, rw);
959 (*_node_data)[vi].heap.push(e, rw);
960 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
963 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
964 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
966 if ((*_blossom_data)[vb].status == MATCHED) {
967 if (_delta2->state(vb) != _delta2->IN_HEAP) {
968 _delta2->push(vb, _blossom_set->classPrio(vb) -
969 (*_blossom_data)[vb].offset);
970 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
971 (*_blossom_data)[vb].offset){
972 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
973 (*_blossom_data)[vb].offset);
980 (*_blossom_data)[blossom].offset = 0;
983 void matchedToOdd(int blossom) {
984 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
985 _delta2->erase(blossom);
987 (*_blossom_data)[blossom].offset += _delta_sum;
988 if (!_blossom_set->trivial(blossom)) {
989 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
990 (*_blossom_data)[blossom].offset);
994 void evenToMatched(int blossom, int tree) {
995 if (!_blossom_set->trivial(blossom)) {
996 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
999 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1000 n != INVALID; ++n) {
1001 int ni = (*_node_index)[n];
1002 (*_node_data)[ni].pot -= _delta_sum;
1006 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1007 Node v = _graph.source(e);
1008 int vb = _blossom_set->find(v);
1009 int vi = (*_node_index)[v];
1011 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1012 dualScale * _weight[e];
1014 if (vb == blossom) {
1015 if (_delta3->state(e) == _delta3->IN_HEAP) {
1018 } else if ((*_blossom_data)[vb].status == EVEN) {
1020 if (_delta3->state(e) == _delta3->IN_HEAP) {
1024 int vt = _tree_set->find(vb);
1028 Arc r = _graph.oppositeArc(e);
1030 typename std::map<int, Arc>::iterator it =
1031 (*_node_data)[ni].heap_index.find(vt);
1033 if (it != (*_node_data)[ni].heap_index.end()) {
1034 if ((*_node_data)[ni].heap[it->second] > rw) {
1035 (*_node_data)[ni].heap.replace(it->second, r);
1036 (*_node_data)[ni].heap.decrease(r, rw);
1040 (*_node_data)[ni].heap.push(r, rw);
1041 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1044 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1045 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1047 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1048 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1049 (*_blossom_data)[blossom].offset);
1050 } else if ((*_delta2)[blossom] >
1051 _blossom_set->classPrio(blossom) -
1052 (*_blossom_data)[blossom].offset){
1053 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1054 (*_blossom_data)[blossom].offset);
1059 } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1060 if (_delta3->state(e) == _delta3->IN_HEAP) {
1065 typename std::map<int, Arc>::iterator it =
1066 (*_node_data)[vi].heap_index.find(tree);
1068 if (it != (*_node_data)[vi].heap_index.end()) {
1069 (*_node_data)[vi].heap.erase(it->second);
1070 (*_node_data)[vi].heap_index.erase(it);
1071 if ((*_node_data)[vi].heap.empty()) {
1072 _blossom_set->increase(v, std::numeric_limits<Value>::max());
1073 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1074 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1077 if ((*_blossom_data)[vb].status == MATCHED) {
1078 if (_blossom_set->classPrio(vb) ==
1079 std::numeric_limits<Value>::max()) {
1081 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1082 (*_blossom_data)[vb].offset) {
1083 _delta2->increase(vb, _blossom_set->classPrio(vb) -
1084 (*_blossom_data)[vb].offset);
1093 void oddToMatched(int blossom) {
1094 (*_blossom_data)[blossom].offset -= _delta_sum;
1096 if (_blossom_set->classPrio(blossom) !=
1097 std::numeric_limits<Value>::max()) {
1098 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1099 (*_blossom_data)[blossom].offset);
1102 if (!_blossom_set->trivial(blossom)) {
1103 _delta4->erase(blossom);
1107 void oddToEven(int blossom, int tree) {
1108 if (!_blossom_set->trivial(blossom)) {
1109 _delta4->erase(blossom);
1110 (*_blossom_data)[blossom].pot -=
1111 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1114 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1115 n != INVALID; ++n) {
1116 int ni = (*_node_index)[n];
1118 _blossom_set->increase(n, std::numeric_limits<Value>::max());
1120 (*_node_data)[ni].heap.clear();
1121 (*_node_data)[ni].heap_index.clear();
1122 (*_node_data)[ni].pot +=
1123 2 * _delta_sum - (*_blossom_data)[blossom].offset;
1125 _delta1->push(n, (*_node_data)[ni].pot);
1127 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1128 Node v = _graph.source(e);
1129 int vb = _blossom_set->find(v);
1130 int vi = (*_node_index)[v];
1132 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1133 dualScale * _weight[e];
1135 if ((*_blossom_data)[vb].status == EVEN) {
1136 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1137 _delta3->push(e, rw / 2);
1139 } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1140 if (_delta3->state(e) != _delta3->IN_HEAP) {
1141 _delta3->push(e, rw);
1145 typename std::map<int, Arc>::iterator it =
1146 (*_node_data)[vi].heap_index.find(tree);
1148 if (it != (*_node_data)[vi].heap_index.end()) {
1149 if ((*_node_data)[vi].heap[it->second] > rw) {
1150 (*_node_data)[vi].heap.replace(it->second, e);
1151 (*_node_data)[vi].heap.decrease(e, rw);
1155 (*_node_data)[vi].heap.push(e, rw);
1156 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1159 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1160 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1162 if ((*_blossom_data)[vb].status == MATCHED) {
1163 if (_delta2->state(vb) != _delta2->IN_HEAP) {
1164 _delta2->push(vb, _blossom_set->classPrio(vb) -
1165 (*_blossom_data)[vb].offset);
1166 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1167 (*_blossom_data)[vb].offset) {
1168 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1169 (*_blossom_data)[vb].offset);
1176 (*_blossom_data)[blossom].offset = 0;
1180 void matchedToUnmatched(int blossom) {
1181 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1182 _delta2->erase(blossom);
1185 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1186 n != INVALID; ++n) {
1187 int ni = (*_node_index)[n];
1189 _blossom_set->increase(n, std::numeric_limits<Value>::max());
1191 (*_node_data)[ni].heap.clear();
1192 (*_node_data)[ni].heap_index.clear();
1194 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1195 Node v = _graph.target(e);
1196 int vb = _blossom_set->find(v);
1197 int vi = (*_node_index)[v];
1199 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1200 dualScale * _weight[e];
1202 if ((*_blossom_data)[vb].status == EVEN) {
1203 if (_delta3->state(e) != _delta3->IN_HEAP) {
1204 _delta3->push(e, rw);
1211 void unmatchedToMatched(int blossom) {
1212 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1213 n != INVALID; ++n) {
1214 int ni = (*_node_index)[n];
1216 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1217 Node v = _graph.source(e);
1218 int vb = _blossom_set->find(v);
1219 int vi = (*_node_index)[v];
1221 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1222 dualScale * _weight[e];
1224 if (vb == blossom) {
1225 if (_delta3->state(e) == _delta3->IN_HEAP) {
1228 } else if ((*_blossom_data)[vb].status == EVEN) {
1230 if (_delta3->state(e) == _delta3->IN_HEAP) {
1234 int vt = _tree_set->find(vb);
1236 Arc r = _graph.oppositeArc(e);
1238 typename std::map<int, Arc>::iterator it =
1239 (*_node_data)[ni].heap_index.find(vt);
1241 if (it != (*_node_data)[ni].heap_index.end()) {
1242 if ((*_node_data)[ni].heap[it->second] > rw) {
1243 (*_node_data)[ni].heap.replace(it->second, r);
1244 (*_node_data)[ni].heap.decrease(r, rw);
1248 (*_node_data)[ni].heap.push(r, rw);
1249 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1252 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1253 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1255 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1256 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1257 (*_blossom_data)[blossom].offset);
1258 } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
1259 (*_blossom_data)[blossom].offset){
1260 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1261 (*_blossom_data)[blossom].offset);
1265 } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1266 if (_delta3->state(e) == _delta3->IN_HEAP) {
1274 void alternatePath(int even, int tree) {
1277 evenToMatched(even, tree);
1278 (*_blossom_data)[even].status = MATCHED;
1280 while ((*_blossom_data)[even].pred != INVALID) {
1281 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1282 (*_blossom_data)[odd].status = MATCHED;
1284 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1286 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1287 (*_blossom_data)[even].status = MATCHED;
1288 evenToMatched(even, tree);
1289 (*_blossom_data)[even].next =
1290 _graph.oppositeArc((*_blossom_data)[odd].pred);
1295 void destroyTree(int tree) {
1296 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1297 if ((*_blossom_data)[b].status == EVEN) {
1298 (*_blossom_data)[b].status = MATCHED;
1299 evenToMatched(b, tree);
1300 } else if ((*_blossom_data)[b].status == ODD) {
1301 (*_blossom_data)[b].status = MATCHED;
1305 _tree_set->eraseClass(tree);
1309 void unmatchNode(const Node& node) {
1310 int blossom = _blossom_set->find(node);
1311 int tree = _tree_set->find(blossom);
1313 alternatePath(blossom, tree);
1316 (*_blossom_data)[blossom].status = UNMATCHED;
1317 (*_blossom_data)[blossom].base = node;
1318 matchedToUnmatched(blossom);
1322 void augmentOnEdge(const Edge& edge) {
1324 int left = _blossom_set->find(_graph.u(edge));
1325 int right = _blossom_set->find(_graph.v(edge));
1327 if ((*_blossom_data)[left].status == EVEN) {
1328 int left_tree = _tree_set->find(left);
1329 alternatePath(left, left_tree);
1330 destroyTree(left_tree);
1332 (*_blossom_data)[left].status = MATCHED;
1333 unmatchedToMatched(left);
1336 if ((*_blossom_data)[right].status == EVEN) {
1337 int right_tree = _tree_set->find(right);
1338 alternatePath(right, right_tree);
1339 destroyTree(right_tree);
1341 (*_blossom_data)[right].status = MATCHED;
1342 unmatchedToMatched(right);
1345 (*_blossom_data)[left].next = _graph.direct(edge, true);
1346 (*_blossom_data)[right].next = _graph.direct(edge, false);
1349 void extendOnArc(const Arc& arc) {
1350 int base = _blossom_set->find(_graph.target(arc));
1351 int tree = _tree_set->find(base);
1353 int odd = _blossom_set->find(_graph.source(arc));
1354 _tree_set->insert(odd, tree);
1355 (*_blossom_data)[odd].status = ODD;
1357 (*_blossom_data)[odd].pred = arc;
1359 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1360 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1361 _tree_set->insert(even, tree);
1362 (*_blossom_data)[even].status = EVEN;
1363 matchedToEven(even, tree);
1366 void shrinkOnEdge(const Edge& edge, int tree) {
1368 std::vector<int> left_path, right_path;
1371 std::set<int> left_set, right_set;
1372 int left = _blossom_set->find(_graph.u(edge));
1373 left_path.push_back(left);
1374 left_set.insert(left);
1376 int right = _blossom_set->find(_graph.v(edge));
1377 right_path.push_back(right);
1378 right_set.insert(right);
1382 if ((*_blossom_data)[left].pred == INVALID) break;
1385 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1386 left_path.push_back(left);
1388 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1389 left_path.push_back(left);
1391 left_set.insert(left);
1393 if (right_set.find(left) != right_set.end()) {
1398 if ((*_blossom_data)[right].pred == INVALID) break;
1401 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1402 right_path.push_back(right);
1404 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1405 right_path.push_back(right);
1407 right_set.insert(right);
1409 if (left_set.find(right) != left_set.end()) {
1417 if ((*_blossom_data)[left].pred == INVALID) {
1419 while (left_set.find(nca) == left_set.end()) {
1421 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1422 right_path.push_back(nca);
1424 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1425 right_path.push_back(nca);
1429 while (right_set.find(nca) == right_set.end()) {
1431 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1432 left_path.push_back(nca);
1434 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1435 left_path.push_back(nca);
1441 std::vector<int> subblossoms;
1444 prev = _graph.direct(edge, true);
1445 for (int i = 0; left_path[i] != nca; i += 2) {
1446 subblossoms.push_back(left_path[i]);
1447 (*_blossom_data)[left_path[i]].next = prev;
1448 _tree_set->erase(left_path[i]);
1450 subblossoms.push_back(left_path[i + 1]);
1451 (*_blossom_data)[left_path[i + 1]].status = EVEN;
1452 oddToEven(left_path[i + 1], tree);
1453 _tree_set->erase(left_path[i + 1]);
1454 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1458 while (right_path[k] != nca) ++k;
1460 subblossoms.push_back(nca);
1461 (*_blossom_data)[nca].next = prev;
1463 for (int i = k - 2; i >= 0; i -= 2) {
1464 subblossoms.push_back(right_path[i + 1]);
1465 (*_blossom_data)[right_path[i + 1]].status = EVEN;
1466 oddToEven(right_path[i + 1], tree);
1467 _tree_set->erase(right_path[i + 1]);
1469 (*_blossom_data)[right_path[i + 1]].next =
1470 (*_blossom_data)[right_path[i + 1]].pred;
1472 subblossoms.push_back(right_path[i]);
1473 _tree_set->erase(right_path[i]);
1477 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1479 for (int i = 0; i < int(subblossoms.size()); ++i) {
1480 if (!_blossom_set->trivial(subblossoms[i])) {
1481 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1483 (*_blossom_data)[subblossoms[i]].status = MATCHED;
1486 (*_blossom_data)[surface].pot = -2 * _delta_sum;
1487 (*_blossom_data)[surface].offset = 0;
1488 (*_blossom_data)[surface].status = EVEN;
1489 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1490 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1492 _tree_set->insert(surface, tree);
1493 _tree_set->erase(nca);
1496 void splitBlossom(int blossom) {
1497 Arc next = (*_blossom_data)[blossom].next;
1498 Arc pred = (*_blossom_data)[blossom].pred;
1500 int tree = _tree_set->find(blossom);
1502 (*_blossom_data)[blossom].status = MATCHED;
1503 oddToMatched(blossom);
1504 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1505 _delta2->erase(blossom);
1508 std::vector<int> subblossoms;
1509 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1511 Value offset = (*_blossom_data)[blossom].offset;
1512 int b = _blossom_set->find(_graph.source(pred));
1513 int d = _blossom_set->find(_graph.source(next));
1515 int ib = -1, id = -1;
1516 for (int i = 0; i < int(subblossoms.size()); ++i) {
1517 if (subblossoms[i] == b) ib = i;
1518 if (subblossoms[i] == d) id = i;
1520 (*_blossom_data)[subblossoms[i]].offset = offset;
1521 if (!_blossom_set->trivial(subblossoms[i])) {
1522 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1524 if (_blossom_set->classPrio(subblossoms[i]) !=
1525 std::numeric_limits<Value>::max()) {
1526 _delta2->push(subblossoms[i],
1527 _blossom_set->classPrio(subblossoms[i]) -
1528 (*_blossom_data)[subblossoms[i]].offset);
1532 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1533 for (int i = (id + 1) % subblossoms.size();
1534 i != ib; i = (i + 2) % subblossoms.size()) {
1535 int sb = subblossoms[i];
1536 int tb = subblossoms[(i + 1) % subblossoms.size()];
1537 (*_blossom_data)[sb].next =
1538 _graph.oppositeArc((*_blossom_data)[tb].next);
1541 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1542 int sb = subblossoms[i];
1543 int tb = subblossoms[(i + 1) % subblossoms.size()];
1544 int ub = subblossoms[(i + 2) % subblossoms.size()];
1546 (*_blossom_data)[sb].status = ODD;
1548 _tree_set->insert(sb, tree);
1549 (*_blossom_data)[sb].pred = pred;
1550 (*_blossom_data)[sb].next =
1551 _graph.oppositeArc((*_blossom_data)[tb].next);
1553 pred = (*_blossom_data)[ub].next;
1555 (*_blossom_data)[tb].status = EVEN;
1556 matchedToEven(tb, tree);
1557 _tree_set->insert(tb, tree);
1558 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1561 (*_blossom_data)[subblossoms[id]].status = ODD;
1562 matchedToOdd(subblossoms[id]);
1563 _tree_set->insert(subblossoms[id], tree);
1564 (*_blossom_data)[subblossoms[id]].next = next;
1565 (*_blossom_data)[subblossoms[id]].pred = pred;
1569 for (int i = (ib + 1) % subblossoms.size();
1570 i != id; i = (i + 2) % subblossoms.size()) {
1571 int sb = subblossoms[i];
1572 int tb = subblossoms[(i + 1) % subblossoms.size()];
1573 (*_blossom_data)[sb].next =
1574 _graph.oppositeArc((*_blossom_data)[tb].next);
1577 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1578 int sb = subblossoms[i];
1579 int tb = subblossoms[(i + 1) % subblossoms.size()];
1580 int ub = subblossoms[(i + 2) % subblossoms.size()];
1582 (*_blossom_data)[sb].status = ODD;
1584 _tree_set->insert(sb, tree);
1585 (*_blossom_data)[sb].next = next;
1586 (*_blossom_data)[sb].pred =
1587 _graph.oppositeArc((*_blossom_data)[tb].next);
1589 (*_blossom_data)[tb].status = EVEN;
1590 matchedToEven(tb, tree);
1591 _tree_set->insert(tb, tree);
1592 (*_blossom_data)[tb].pred =
1593 (*_blossom_data)[tb].next =
1594 _graph.oppositeArc((*_blossom_data)[ub].next);
1595 next = (*_blossom_data)[ub].next;
1598 (*_blossom_data)[subblossoms[ib]].status = ODD;
1599 matchedToOdd(subblossoms[ib]);
1600 _tree_set->insert(subblossoms[ib], tree);
1601 (*_blossom_data)[subblossoms[ib]].next = next;
1602 (*_blossom_data)[subblossoms[ib]].pred = pred;
1604 _tree_set->erase(blossom);
1607 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1608 if (_blossom_set->trivial(blossom)) {
1609 int bi = (*_node_index)[base];
1610 Value pot = (*_node_data)[bi].pot;
1612 (*_matching)[base] = matching;
1613 _blossom_node_list.push_back(base);
1614 (*_node_potential)[base] = pot;
1617 Value pot = (*_blossom_data)[blossom].pot;
1618 int bn = _blossom_node_list.size();
1620 std::vector<int> subblossoms;
1621 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1622 int b = _blossom_set->find(base);
1624 for (int i = 0; i < int(subblossoms.size()); ++i) {
1625 if (subblossoms[i] == b) { ib = i; break; }
1628 for (int i = 1; i < int(subblossoms.size()); i += 2) {
1629 int sb = subblossoms[(ib + i) % subblossoms.size()];
1630 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1632 Arc m = (*_blossom_data)[tb].next;
1633 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1634 extractBlossom(tb, _graph.source(m), m);
1636 extractBlossom(subblossoms[ib], base, matching);
1638 int en = _blossom_node_list.size();
1640 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1644 void extractMatching() {
1645 std::vector<int> blossoms;
1646 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1647 blossoms.push_back(c);
1650 for (int i = 0; i < int(blossoms.size()); ++i) {
1651 if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
1653 Value offset = (*_blossom_data)[blossoms[i]].offset;
1654 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1655 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1656 n != INVALID; ++n) {
1657 (*_node_data)[(*_node_index)[n]].pot -= offset;
1660 Arc matching = (*_blossom_data)[blossoms[i]].next;
1661 Node base = _graph.source(matching);
1662 extractBlossom(blossoms[i], base, matching);
1664 Node base = (*_blossom_data)[blossoms[i]].base;
1665 extractBlossom(blossoms[i], base, INVALID);
1672 /// \brief Constructor
1675 MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1676 : _graph(graph), _weight(weight), _matching(0),
1677 _node_potential(0), _blossom_potential(), _blossom_node_list(),
1678 _node_num(0), _blossom_num(0),
1680 _blossom_index(0), _blossom_set(0), _blossom_data(0),
1681 _node_index(0), _node_heap_index(0), _node_data(0),
1682 _tree_set_index(0), _tree_set(0),
1684 _delta1_index(0), _delta1(0),
1685 _delta2_index(0), _delta2(0),
1686 _delta3_index(0), _delta3(0),
1687 _delta4_index(0), _delta4(0),
1691 ~MaxWeightedMatching() {
1692 destroyStructures();
1695 /// \name Execution Control
1696 /// The simplest way to execute the algorithm is to use the
1697 /// \ref run() member function.
1701 /// \brief Initialize the algorithm
1703 /// This function initializes the algorithm.
1707 _blossom_node_list.clear();
1708 _blossom_potential.clear();
1710 for (ArcIt e(_graph); e != INVALID; ++e) {
1711 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1713 for (NodeIt n(_graph); n != INVALID; ++n) {
1714 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1716 for (EdgeIt e(_graph); e != INVALID; ++e) {
1717 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1719 for (int i = 0; i < _blossom_num; ++i) {
1720 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1721 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1728 _blossom_set->clear();
1732 for (NodeIt n(_graph); n != INVALID; ++n) {
1734 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1735 if (_graph.target(e) == n) continue;
1736 if ((dualScale * _weight[e]) / 2 > max) {
1737 max = (dualScale * _weight[e]) / 2;
1740 (*_node_index)[n] = index;
1741 (*_node_data)[index].heap_index.clear();
1742 (*_node_data)[index].heap.clear();
1743 (*_node_data)[index].pot = max;
1744 _delta1->push(n, max);
1746 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1748 _tree_set->insert(blossom);
1750 (*_blossom_data)[blossom].status = EVEN;
1751 (*_blossom_data)[blossom].pred = INVALID;
1752 (*_blossom_data)[blossom].next = INVALID;
1753 (*_blossom_data)[blossom].pot = 0;
1754 (*_blossom_data)[blossom].offset = 0;
1757 for (EdgeIt e(_graph); e != INVALID; ++e) {
1758 int si = (*_node_index)[_graph.u(e)];
1759 int ti = (*_node_index)[_graph.v(e)];
1760 if (_graph.u(e) != _graph.v(e)) {
1761 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1762 dualScale * _weight[e]) / 2);
1767 /// \brief Start the algorithm
1769 /// This function starts the algorithm.
1771 /// \pre \ref init() must be called before using this function.
1777 int unmatched = _node_num;
1778 while (unmatched > 0) {
1779 Value d1 = !_delta1->empty() ?
1780 _delta1->prio() : std::numeric_limits<Value>::max();
1782 Value d2 = !_delta2->empty() ?
1783 _delta2->prio() : std::numeric_limits<Value>::max();
1785 Value d3 = !_delta3->empty() ?
1786 _delta3->prio() : std::numeric_limits<Value>::max();
1788 Value d4 = !_delta4->empty() ?
1789 _delta4->prio() : std::numeric_limits<Value>::max();
1791 _delta_sum = d1; OpType ot = D1;
1792 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1793 if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
1794 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1800 Node n = _delta1->top();
1807 int blossom = _delta2->top();
1808 Node n = _blossom_set->classTop(blossom);
1809 Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
1815 Edge e = _delta3->top();
1817 int left_blossom = _blossom_set->find(_graph.u(e));
1818 int right_blossom = _blossom_set->find(_graph.v(e));
1820 if (left_blossom == right_blossom) {
1824 if ((*_blossom_data)[left_blossom].status == EVEN) {
1825 left_tree = _tree_set->find(left_blossom);
1831 if ((*_blossom_data)[right_blossom].status == EVEN) {
1832 right_tree = _tree_set->find(right_blossom);
1838 if (left_tree == right_tree) {
1839 shrinkOnEdge(e, left_tree);
1847 splitBlossom(_delta4->top());
1854 /// \brief Run the algorithm.
1856 /// This method runs the \c %MaxWeightedMatching algorithm.
1858 /// \note mwm.run() is just a shortcut of the following code.
1870 /// \name Primal Solution
1871 /// Functions to get the primal solution, i.e. the maximum weighted
1873 /// Either \ref run() or \ref start() function should be called before
1878 /// \brief Return the weight of the matching.
1880 /// This function returns the weight of the found matching.
1882 /// \pre Either run() or start() must be called before using this function.
1883 Value matchingWeight() const {
1885 for (NodeIt n(_graph); n != INVALID; ++n) {
1886 if ((*_matching)[n] != INVALID) {
1887 sum += _weight[(*_matching)[n]];
1893 /// \brief Return the size (cardinality) of the matching.
1895 /// This function returns the size (cardinality) of the found matching.
1897 /// \pre Either run() or start() must be called before using this function.
1898 int matchingSize() const {
1900 for (NodeIt n(_graph); n != INVALID; ++n) {
1901 if ((*_matching)[n] != INVALID) {
1908 /// \brief Return \c true if the given edge is in the matching.
1910 /// This function returns \c true if the given edge is in the found
1913 /// \pre Either run() or start() must be called before using this function.
1914 bool matching(const Edge& edge) const {
1915 return edge == (*_matching)[_graph.u(edge)];
1918 /// \brief Return the matching arc (or edge) incident to the given node.
1920 /// This function returns the matching arc (or edge) incident to the
1921 /// given node in the found matching or \c INVALID if the node is
1922 /// not covered by the matching.
1924 /// \pre Either run() or start() must be called before using this function.
1925 Arc matching(const Node& node) const {
1926 return (*_matching)[node];
1929 /// \brief Return a const reference to the matching map.
1931 /// This function returns a const reference to a node map that stores
1932 /// the matching arc (or edge) incident to each node.
1933 const MatchingMap& matchingMap() const {
1937 /// \brief Return the mate of the given node.
1939 /// This function returns the mate of the given node in the found
1940 /// matching or \c INVALID if the node is not covered by the matching.
1942 /// \pre Either run() or start() must be called before using this function.
1943 Node mate(const Node& node) const {
1944 return (*_matching)[node] != INVALID ?
1945 _graph.target((*_matching)[node]) : INVALID;
1950 /// \name Dual Solution
1951 /// Functions to get the dual solution.\n
1952 /// Either \ref run() or \ref start() function should be called before
1957 /// \brief Return the value of the dual solution.
1959 /// This function returns the value of the dual solution.
1960 /// It should be equal to the primal value scaled by \ref dualScale
1963 /// \pre Either run() or start() must be called before using this function.
1964 Value dualValue() const {
1966 for (NodeIt n(_graph); n != INVALID; ++n) {
1967 sum += nodeValue(n);
1969 for (int i = 0; i < blossomNum(); ++i) {
1970 sum += blossomValue(i) * (blossomSize(i) / 2);
1975 /// \brief Return the dual value (potential) of the given node.
1977 /// This function returns the dual value (potential) of the given node.
1979 /// \pre Either run() or start() must be called before using this function.
1980 Value nodeValue(const Node& n) const {
1981 return (*_node_potential)[n];
1984 /// \brief Return the number of the blossoms in the basis.
1986 /// This function returns the number of the blossoms in the basis.
1988 /// \pre Either run() or start() must be called before using this function.
1990 int blossomNum() const {
1991 return _blossom_potential.size();
1994 /// \brief Return the number of the nodes in the given blossom.
1996 /// This function returns the number of the nodes in the given blossom.
1998 /// \pre Either run() or start() must be called before using this function.
2000 int blossomSize(int k) const {
2001 return _blossom_potential[k].end - _blossom_potential[k].begin;
2004 /// \brief Return the dual value (ptential) of the given blossom.
2006 /// This function returns the dual value (ptential) of the given blossom.
2008 /// \pre Either run() or start() must be called before using this function.
2009 Value blossomValue(int k) const {
2010 return _blossom_potential[k].value;
2013 /// \brief Iterator for obtaining the nodes of a blossom.
2015 /// This class provides an iterator for obtaining the nodes of the
2016 /// given blossom. It lists a subset of the nodes.
2017 /// Before using this iterator, you must allocate a
2018 /// MaxWeightedMatching class and execute it.
2022 /// \brief Constructor.
2024 /// Constructor to get the nodes of the given variable.
2026 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
2027 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
2028 /// called before initializing this iterator.
2029 BlossomIt(const MaxWeightedMatching& algorithm, int variable)
2030 : _algorithm(&algorithm)
2032 _index = _algorithm->_blossom_potential[variable].begin;
2033 _last = _algorithm->_blossom_potential[variable].end;
2036 /// \brief Conversion to \c Node.
2038 /// Conversion to \c Node.
2039 operator Node() const {
2040 return _algorithm->_blossom_node_list[_index];
2043 /// \brief Increment operator.
2045 /// Increment operator.
2046 BlossomIt& operator++() {
2051 /// \brief Validity checking
2053 /// Checks whether the iterator is invalid.
2054 bool operator==(Invalid) const { return _index == _last; }
2056 /// \brief Validity checking
2058 /// Checks whether the iterator is valid.
2059 bool operator!=(Invalid) const { return _index != _last; }
2062 const MaxWeightedMatching* _algorithm;
2071 /// \ingroup matching
2073 /// \brief Weighted perfect matching in general graphs
2075 /// This class provides an efficient implementation of Edmond's
2076 /// maximum weighted perfect matching algorithm. The implementation
2077 /// is based on extensive use of priority queues and provides
2078 /// \f$O(nm\log n)\f$ time complexity.
2080 /// The maximum weighted perfect matching problem is to find a subset of
2081 /// the edges in an undirected graph with maximum overall weight for which
2082 /// each node has exactly one incident edge.
2083 /// It can be formulated with the following linear program.
2084 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
2085 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2086 \quad \forall B\in\mathcal{O}\f] */
2087 /// \f[x_e \ge 0\quad \forall e\in E\f]
2088 /// \f[\max \sum_{e\in E}x_ew_e\f]
2089 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2090 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2091 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2092 /// subsets of the nodes.
2094 /// The algorithm calculates an optimal matching and a proof of the
2095 /// optimality. The solution of the dual problem can be used to check
2096 /// the result of the algorithm. The dual linear problem is the
2098 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
2099 w_{uv} \quad \forall uv\in E\f] */
2100 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2101 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2102 \frac{\vert B \vert - 1}{2}z_B\f] */
2104 /// The algorithm can be executed with the run() function.
2105 /// After it the matching (the primal solution) and the dual solution
2106 /// can be obtained using the query functions and the
2107 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
2108 /// which is able to iterate on the nodes of a blossom.
2109 /// If the value type is integer, then the dual solution is multiplied
2110 /// by \ref MaxWeightedMatching::dualScale "4".
2112 /// \tparam GR The undirected graph type the algorithm runs on.
2113 /// \tparam WM The type edge weight map. The default type is
2114 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2116 template <typename GR, typename WM>
2118 template <typename GR,
2119 typename WM = typename GR::template EdgeMap<int> >
2121 class MaxWeightedPerfectMatching {
2124 /// The graph type of the algorithm
2126 /// The type of the edge weight map
2127 typedef WM WeightMap;
2128 /// The value type of the edge weights
2129 typedef typename WeightMap::Value Value;
2131 /// \brief Scaling factor for dual solution
2133 /// Scaling factor for dual solution, it is equal to 4 or 1
2134 /// according to the value type.
2135 static const int dualScale =
2136 std::numeric_limits<Value>::is_integer ? 4 : 1;
2138 /// The type of the matching map
2139 typedef typename Graph::template NodeMap<typename Graph::Arc>
2144 TEMPLATE_GRAPH_TYPEDEFS(Graph);
2146 typedef typename Graph::template NodeMap<Value> NodePotential;
2147 typedef std::vector<Node> BlossomNodeList;
2149 struct BlossomVariable {
2153 BlossomVariable(int _begin, int _end, Value _value)
2154 : begin(_begin), end(_end), value(_value) {}
2158 typedef std::vector<BlossomVariable> BlossomPotential;
2160 const Graph& _graph;
2161 const WeightMap& _weight;
2163 MatchingMap* _matching;
2165 NodePotential* _node_potential;
2167 BlossomPotential _blossom_potential;
2168 BlossomNodeList _blossom_node_list;
2173 typedef RangeMap<int> IntIntMap;
2176 EVEN = -1, MATCHED = 0, ODD = 1
2179 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2180 struct BlossomData {
2187 IntNodeMap *_blossom_index;
2188 BlossomSet *_blossom_set;
2189 RangeMap<BlossomData>* _blossom_data;
2191 IntNodeMap *_node_index;
2192 IntArcMap *_node_heap_index;
2196 NodeData(IntArcMap& node_heap_index)
2197 : heap(node_heap_index) {}
2201 BinHeap<Value, IntArcMap> heap;
2202 std::map<int, Arc> heap_index;
2207 RangeMap<NodeData>* _node_data;
2209 typedef ExtendFindEnum<IntIntMap> TreeSet;
2211 IntIntMap *_tree_set_index;
2214 IntIntMap *_delta2_index;
2215 BinHeap<Value, IntIntMap> *_delta2;
2217 IntEdgeMap *_delta3_index;
2218 BinHeap<Value, IntEdgeMap> *_delta3;
2220 IntIntMap *_delta4_index;
2221 BinHeap<Value, IntIntMap> *_delta4;
2225 void createStructures() {
2226 _node_num = countNodes(_graph);
2227 _blossom_num = _node_num * 3 / 2;
2230 _matching = new MatchingMap(_graph);
2233 if (!_node_potential) {
2234 _node_potential = new NodePotential(_graph);
2237 if (!_blossom_set) {
2238 _blossom_index = new IntNodeMap(_graph);
2239 _blossom_set = new BlossomSet(*_blossom_index);
2240 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2241 } else if (_blossom_data->size() != _blossom_num) {
2242 delete _blossom_data;
2243 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2247 _node_index = new IntNodeMap(_graph);
2248 _node_heap_index = new IntArcMap(_graph);
2249 _node_data = new RangeMap<NodeData>(_node_num,
2250 NodeData(*_node_heap_index));
2251 } else if (_node_data->size() != _node_num) {
2253 _node_data = new RangeMap<NodeData>(_node_num,
2254 NodeData(*_node_heap_index));
2258 _tree_set_index = new IntIntMap(_blossom_num);
2259 _tree_set = new TreeSet(*_tree_set_index);
2261 _tree_set_index->resize(_blossom_num);
2265 _delta2_index = new IntIntMap(_blossom_num);
2266 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2268 _delta2_index->resize(_blossom_num);
2272 _delta3_index = new IntEdgeMap(_graph);
2273 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2277 _delta4_index = new IntIntMap(_blossom_num);
2278 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2280 _delta4_index->resize(_blossom_num);
2284 void destroyStructures() {
2285 _node_num = countNodes(_graph);
2286 _blossom_num = _node_num * 3 / 2;
2291 if (_node_potential) {
2292 delete _node_potential;
2295 delete _blossom_index;
2296 delete _blossom_set;
2297 delete _blossom_data;
2302 delete _node_heap_index;
2307 delete _tree_set_index;
2311 delete _delta2_index;
2315 delete _delta3_index;
2319 delete _delta4_index;
2324 void matchedToEven(int blossom, int tree) {
2325 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2326 _delta2->erase(blossom);
2329 if (!_blossom_set->trivial(blossom)) {
2330 (*_blossom_data)[blossom].pot -=
2331 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2334 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2335 n != INVALID; ++n) {
2337 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2338 int ni = (*_node_index)[n];
2340 (*_node_data)[ni].heap.clear();
2341 (*_node_data)[ni].heap_index.clear();
2343 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2345 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2346 Node v = _graph.source(e);
2347 int vb = _blossom_set->find(v);
2348 int vi = (*_node_index)[v];
2350 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2351 dualScale * _weight[e];
2353 if ((*_blossom_data)[vb].status == EVEN) {
2354 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2355 _delta3->push(e, rw / 2);
2358 typename std::map<int, Arc>::iterator it =
2359 (*_node_data)[vi].heap_index.find(tree);
2361 if (it != (*_node_data)[vi].heap_index.end()) {
2362 if ((*_node_data)[vi].heap[it->second] > rw) {
2363 (*_node_data)[vi].heap.replace(it->second, e);
2364 (*_node_data)[vi].heap.decrease(e, rw);
2368 (*_node_data)[vi].heap.push(e, rw);
2369 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2372 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2373 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2375 if ((*_blossom_data)[vb].status == MATCHED) {
2376 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2377 _delta2->push(vb, _blossom_set->classPrio(vb) -
2378 (*_blossom_data)[vb].offset);
2379 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2380 (*_blossom_data)[vb].offset){
2381 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2382 (*_blossom_data)[vb].offset);
2389 (*_blossom_data)[blossom].offset = 0;
2392 void matchedToOdd(int blossom) {
2393 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2394 _delta2->erase(blossom);
2396 (*_blossom_data)[blossom].offset += _delta_sum;
2397 if (!_blossom_set->trivial(blossom)) {
2398 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2399 (*_blossom_data)[blossom].offset);
2403 void evenToMatched(int blossom, int tree) {
2404 if (!_blossom_set->trivial(blossom)) {
2405 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2408 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2409 n != INVALID; ++n) {
2410 int ni = (*_node_index)[n];
2411 (*_node_data)[ni].pot -= _delta_sum;
2413 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2414 Node v = _graph.source(e);
2415 int vb = _blossom_set->find(v);
2416 int vi = (*_node_index)[v];
2418 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2419 dualScale * _weight[e];
2421 if (vb == blossom) {
2422 if (_delta3->state(e) == _delta3->IN_HEAP) {
2425 } else if ((*_blossom_data)[vb].status == EVEN) {
2427 if (_delta3->state(e) == _delta3->IN_HEAP) {
2431 int vt = _tree_set->find(vb);
2435 Arc r = _graph.oppositeArc(e);
2437 typename std::map<int, Arc>::iterator it =
2438 (*_node_data)[ni].heap_index.find(vt);
2440 if (it != (*_node_data)[ni].heap_index.end()) {
2441 if ((*_node_data)[ni].heap[it->second] > rw) {
2442 (*_node_data)[ni].heap.replace(it->second, r);
2443 (*_node_data)[ni].heap.decrease(r, rw);
2447 (*_node_data)[ni].heap.push(r, rw);
2448 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2451 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2452 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2454 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2455 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2456 (*_blossom_data)[blossom].offset);
2457 } else if ((*_delta2)[blossom] >
2458 _blossom_set->classPrio(blossom) -
2459 (*_blossom_data)[blossom].offset){
2460 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2461 (*_blossom_data)[blossom].offset);
2467 typename std::map<int, Arc>::iterator it =
2468 (*_node_data)[vi].heap_index.find(tree);
2470 if (it != (*_node_data)[vi].heap_index.end()) {
2471 (*_node_data)[vi].heap.erase(it->second);
2472 (*_node_data)[vi].heap_index.erase(it);
2473 if ((*_node_data)[vi].heap.empty()) {
2474 _blossom_set->increase(v, std::numeric_limits<Value>::max());
2475 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2476 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2479 if ((*_blossom_data)[vb].status == MATCHED) {
2480 if (_blossom_set->classPrio(vb) ==
2481 std::numeric_limits<Value>::max()) {
2483 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2484 (*_blossom_data)[vb].offset) {
2485 _delta2->increase(vb, _blossom_set->classPrio(vb) -
2486 (*_blossom_data)[vb].offset);
2495 void oddToMatched(int blossom) {
2496 (*_blossom_data)[blossom].offset -= _delta_sum;
2498 if (_blossom_set->classPrio(blossom) !=
2499 std::numeric_limits<Value>::max()) {
2500 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2501 (*_blossom_data)[blossom].offset);
2504 if (!_blossom_set->trivial(blossom)) {
2505 _delta4->erase(blossom);
2509 void oddToEven(int blossom, int tree) {
2510 if (!_blossom_set->trivial(blossom)) {
2511 _delta4->erase(blossom);
2512 (*_blossom_data)[blossom].pot -=
2513 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2516 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2517 n != INVALID; ++n) {
2518 int ni = (*_node_index)[n];
2520 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2522 (*_node_data)[ni].heap.clear();
2523 (*_node_data)[ni].heap_index.clear();
2524 (*_node_data)[ni].pot +=
2525 2 * _delta_sum - (*_blossom_data)[blossom].offset;
2527 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2528 Node v = _graph.source(e);
2529 int vb = _blossom_set->find(v);
2530 int vi = (*_node_index)[v];
2532 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2533 dualScale * _weight[e];
2535 if ((*_blossom_data)[vb].status == EVEN) {
2536 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2537 _delta3->push(e, rw / 2);
2541 typename std::map<int, Arc>::iterator it =
2542 (*_node_data)[vi].heap_index.find(tree);
2544 if (it != (*_node_data)[vi].heap_index.end()) {
2545 if ((*_node_data)[vi].heap[it->second] > rw) {
2546 (*_node_data)[vi].heap.replace(it->second, e);
2547 (*_node_data)[vi].heap.decrease(e, rw);
2551 (*_node_data)[vi].heap.push(e, rw);
2552 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2555 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2556 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2558 if ((*_blossom_data)[vb].status == MATCHED) {
2559 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2560 _delta2->push(vb, _blossom_set->classPrio(vb) -
2561 (*_blossom_data)[vb].offset);
2562 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2563 (*_blossom_data)[vb].offset) {
2564 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2565 (*_blossom_data)[vb].offset);
2572 (*_blossom_data)[blossom].offset = 0;
2575 void alternatePath(int even, int tree) {
2578 evenToMatched(even, tree);
2579 (*_blossom_data)[even].status = MATCHED;
2581 while ((*_blossom_data)[even].pred != INVALID) {
2582 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2583 (*_blossom_data)[odd].status = MATCHED;
2585 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2587 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2588 (*_blossom_data)[even].status = MATCHED;
2589 evenToMatched(even, tree);
2590 (*_blossom_data)[even].next =
2591 _graph.oppositeArc((*_blossom_data)[odd].pred);
2596 void destroyTree(int tree) {
2597 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2598 if ((*_blossom_data)[b].status == EVEN) {
2599 (*_blossom_data)[b].status = MATCHED;
2600 evenToMatched(b, tree);
2601 } else if ((*_blossom_data)[b].status == ODD) {
2602 (*_blossom_data)[b].status = MATCHED;
2606 _tree_set->eraseClass(tree);
2609 void augmentOnEdge(const Edge& edge) {
2611 int left = _blossom_set->find(_graph.u(edge));
2612 int right = _blossom_set->find(_graph.v(edge));
2614 int left_tree = _tree_set->find(left);
2615 alternatePath(left, left_tree);
2616 destroyTree(left_tree);
2618 int right_tree = _tree_set->find(right);
2619 alternatePath(right, right_tree);
2620 destroyTree(right_tree);
2622 (*_blossom_data)[left].next = _graph.direct(edge, true);
2623 (*_blossom_data)[right].next = _graph.direct(edge, false);
2626 void extendOnArc(const Arc& arc) {
2627 int base = _blossom_set->find(_graph.target(arc));
2628 int tree = _tree_set->find(base);
2630 int odd = _blossom_set->find(_graph.source(arc));
2631 _tree_set->insert(odd, tree);
2632 (*_blossom_data)[odd].status = ODD;
2634 (*_blossom_data)[odd].pred = arc;
2636 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2637 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2638 _tree_set->insert(even, tree);
2639 (*_blossom_data)[even].status = EVEN;
2640 matchedToEven(even, tree);
2643 void shrinkOnEdge(const Edge& edge, int tree) {
2645 std::vector<int> left_path, right_path;
2648 std::set<int> left_set, right_set;
2649 int left = _blossom_set->find(_graph.u(edge));
2650 left_path.push_back(left);
2651 left_set.insert(left);
2653 int right = _blossom_set->find(_graph.v(edge));
2654 right_path.push_back(right);
2655 right_set.insert(right);
2659 if ((*_blossom_data)[left].pred == INVALID) break;
2662 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2663 left_path.push_back(left);
2665 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2666 left_path.push_back(left);
2668 left_set.insert(left);
2670 if (right_set.find(left) != right_set.end()) {
2675 if ((*_blossom_data)[right].pred == INVALID) break;
2678 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2679 right_path.push_back(right);
2681 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2682 right_path.push_back(right);
2684 right_set.insert(right);
2686 if (left_set.find(right) != left_set.end()) {
2694 if ((*_blossom_data)[left].pred == INVALID) {
2696 while (left_set.find(nca) == left_set.end()) {
2698 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2699 right_path.push_back(nca);
2701 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2702 right_path.push_back(nca);
2706 while (right_set.find(nca) == right_set.end()) {
2708 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2709 left_path.push_back(nca);
2711 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2712 left_path.push_back(nca);
2718 std::vector<int> subblossoms;
2721 prev = _graph.direct(edge, true);
2722 for (int i = 0; left_path[i] != nca; i += 2) {
2723 subblossoms.push_back(left_path[i]);
2724 (*_blossom_data)[left_path[i]].next = prev;
2725 _tree_set->erase(left_path[i]);
2727 subblossoms.push_back(left_path[i + 1]);
2728 (*_blossom_data)[left_path[i + 1]].status = EVEN;
2729 oddToEven(left_path[i + 1], tree);
2730 _tree_set->erase(left_path[i + 1]);
2731 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2735 while (right_path[k] != nca) ++k;
2737 subblossoms.push_back(nca);
2738 (*_blossom_data)[nca].next = prev;
2740 for (int i = k - 2; i >= 0; i -= 2) {
2741 subblossoms.push_back(right_path[i + 1]);
2742 (*_blossom_data)[right_path[i + 1]].status = EVEN;
2743 oddToEven(right_path[i + 1], tree);
2744 _tree_set->erase(right_path[i + 1]);
2746 (*_blossom_data)[right_path[i + 1]].next =
2747 (*_blossom_data)[right_path[i + 1]].pred;
2749 subblossoms.push_back(right_path[i]);
2750 _tree_set->erase(right_path[i]);
2754 _blossom_set->join(subblossoms.begin(), subblossoms.end());
2756 for (int i = 0; i < int(subblossoms.size()); ++i) {
2757 if (!_blossom_set->trivial(subblossoms[i])) {
2758 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2760 (*_blossom_data)[subblossoms[i]].status = MATCHED;
2763 (*_blossom_data)[surface].pot = -2 * _delta_sum;
2764 (*_blossom_data)[surface].offset = 0;
2765 (*_blossom_data)[surface].status = EVEN;
2766 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2767 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2769 _tree_set->insert(surface, tree);
2770 _tree_set->erase(nca);
2773 void splitBlossom(int blossom) {
2774 Arc next = (*_blossom_data)[blossom].next;
2775 Arc pred = (*_blossom_data)[blossom].pred;
2777 int tree = _tree_set->find(blossom);
2779 (*_blossom_data)[blossom].status = MATCHED;
2780 oddToMatched(blossom);
2781 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2782 _delta2->erase(blossom);
2785 std::vector<int> subblossoms;
2786 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2788 Value offset = (*_blossom_data)[blossom].offset;
2789 int b = _blossom_set->find(_graph.source(pred));
2790 int d = _blossom_set->find(_graph.source(next));
2792 int ib = -1, id = -1;
2793 for (int i = 0; i < int(subblossoms.size()); ++i) {
2794 if (subblossoms[i] == b) ib = i;
2795 if (subblossoms[i] == d) id = i;
2797 (*_blossom_data)[subblossoms[i]].offset = offset;
2798 if (!_blossom_set->trivial(subblossoms[i])) {
2799 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2801 if (_blossom_set->classPrio(subblossoms[i]) !=
2802 std::numeric_limits<Value>::max()) {
2803 _delta2->push(subblossoms[i],
2804 _blossom_set->classPrio(subblossoms[i]) -
2805 (*_blossom_data)[subblossoms[i]].offset);
2809 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2810 for (int i = (id + 1) % subblossoms.size();
2811 i != ib; i = (i + 2) % subblossoms.size()) {
2812 int sb = subblossoms[i];
2813 int tb = subblossoms[(i + 1) % subblossoms.size()];
2814 (*_blossom_data)[sb].next =
2815 _graph.oppositeArc((*_blossom_data)[tb].next);
2818 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2819 int sb = subblossoms[i];
2820 int tb = subblossoms[(i + 1) % subblossoms.size()];
2821 int ub = subblossoms[(i + 2) % subblossoms.size()];
2823 (*_blossom_data)[sb].status = ODD;
2825 _tree_set->insert(sb, tree);
2826 (*_blossom_data)[sb].pred = pred;
2827 (*_blossom_data)[sb].next =
2828 _graph.oppositeArc((*_blossom_data)[tb].next);
2830 pred = (*_blossom_data)[ub].next;
2832 (*_blossom_data)[tb].status = EVEN;
2833 matchedToEven(tb, tree);
2834 _tree_set->insert(tb, tree);
2835 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2838 (*_blossom_data)[subblossoms[id]].status = ODD;
2839 matchedToOdd(subblossoms[id]);
2840 _tree_set->insert(subblossoms[id], tree);
2841 (*_blossom_data)[subblossoms[id]].next = next;
2842 (*_blossom_data)[subblossoms[id]].pred = pred;
2846 for (int i = (ib + 1) % subblossoms.size();
2847 i != id; i = (i + 2) % subblossoms.size()) {
2848 int sb = subblossoms[i];
2849 int tb = subblossoms[(i + 1) % subblossoms.size()];
2850 (*_blossom_data)[sb].next =
2851 _graph.oppositeArc((*_blossom_data)[tb].next);
2854 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
2855 int sb = subblossoms[i];
2856 int tb = subblossoms[(i + 1) % subblossoms.size()];
2857 int ub = subblossoms[(i + 2) % subblossoms.size()];
2859 (*_blossom_data)[sb].status = ODD;
2861 _tree_set->insert(sb, tree);
2862 (*_blossom_data)[sb].next = next;
2863 (*_blossom_data)[sb].pred =
2864 _graph.oppositeArc((*_blossom_data)[tb].next);
2866 (*_blossom_data)[tb].status = EVEN;
2867 matchedToEven(tb, tree);
2868 _tree_set->insert(tb, tree);
2869 (*_blossom_data)[tb].pred =
2870 (*_blossom_data)[tb].next =
2871 _graph.oppositeArc((*_blossom_data)[ub].next);
2872 next = (*_blossom_data)[ub].next;
2875 (*_blossom_data)[subblossoms[ib]].status = ODD;
2876 matchedToOdd(subblossoms[ib]);
2877 _tree_set->insert(subblossoms[ib], tree);
2878 (*_blossom_data)[subblossoms[ib]].next = next;
2879 (*_blossom_data)[subblossoms[ib]].pred = pred;
2881 _tree_set->erase(blossom);
2884 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2885 if (_blossom_set->trivial(blossom)) {
2886 int bi = (*_node_index)[base];
2887 Value pot = (*_node_data)[bi].pot;
2889 (*_matching)[base] = matching;
2890 _blossom_node_list.push_back(base);
2891 (*_node_potential)[base] = pot;
2894 Value pot = (*_blossom_data)[blossom].pot;
2895 int bn = _blossom_node_list.size();
2897 std::vector<int> subblossoms;
2898 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2899 int b = _blossom_set->find(base);
2901 for (int i = 0; i < int(subblossoms.size()); ++i) {
2902 if (subblossoms[i] == b) { ib = i; break; }
2905 for (int i = 1; i < int(subblossoms.size()); i += 2) {
2906 int sb = subblossoms[(ib + i) % subblossoms.size()];
2907 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2909 Arc m = (*_blossom_data)[tb].next;
2910 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2911 extractBlossom(tb, _graph.source(m), m);
2913 extractBlossom(subblossoms[ib], base, matching);
2915 int en = _blossom_node_list.size();
2917 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2921 void extractMatching() {
2922 std::vector<int> blossoms;
2923 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2924 blossoms.push_back(c);
2927 for (int i = 0; i < int(blossoms.size()); ++i) {
2929 Value offset = (*_blossom_data)[blossoms[i]].offset;
2930 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2931 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2932 n != INVALID; ++n) {
2933 (*_node_data)[(*_node_index)[n]].pot -= offset;
2936 Arc matching = (*_blossom_data)[blossoms[i]].next;
2937 Node base = _graph.source(matching);
2938 extractBlossom(blossoms[i], base, matching);
2944 /// \brief Constructor
2947 MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2948 : _graph(graph), _weight(weight), _matching(0),
2949 _node_potential(0), _blossom_potential(), _blossom_node_list(),
2950 _node_num(0), _blossom_num(0),
2952 _blossom_index(0), _blossom_set(0), _blossom_data(0),
2953 _node_index(0), _node_heap_index(0), _node_data(0),
2954 _tree_set_index(0), _tree_set(0),
2956 _delta2_index(0), _delta2(0),
2957 _delta3_index(0), _delta3(0),
2958 _delta4_index(0), _delta4(0),
2962 ~MaxWeightedPerfectMatching() {
2963 destroyStructures();
2966 /// \name Execution Control
2967 /// The simplest way to execute the algorithm is to use the
2968 /// \ref run() member function.
2972 /// \brief Initialize the algorithm
2974 /// This function initializes the algorithm.
2978 _blossom_node_list.clear();
2979 _blossom_potential.clear();
2981 for (ArcIt e(_graph); e != INVALID; ++e) {
2982 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2984 for (EdgeIt e(_graph); e != INVALID; ++e) {
2985 (*_delta3_index)[e] = _delta3->PRE_HEAP;
2987 for (int i = 0; i < _blossom_num; ++i) {
2988 (*_delta2_index)[i] = _delta2->PRE_HEAP;
2989 (*_delta4_index)[i] = _delta4->PRE_HEAP;
2995 _blossom_set->clear();
2999 for (NodeIt n(_graph); n != INVALID; ++n) {
3000 Value max = - std::numeric_limits<Value>::max();
3001 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
3002 if (_graph.target(e) == n) continue;
3003 if ((dualScale * _weight[e]) / 2 > max) {
3004 max = (dualScale * _weight[e]) / 2;
3007 (*_node_index)[n] = index;
3008 (*_node_data)[index].heap_index.clear();
3009 (*_node_data)[index].heap.clear();
3010 (*_node_data)[index].pot = max;
3012 _blossom_set->insert(n, std::numeric_limits<Value>::max());
3014 _tree_set->insert(blossom);
3016 (*_blossom_data)[blossom].status = EVEN;
3017 (*_blossom_data)[blossom].pred = INVALID;
3018 (*_blossom_data)[blossom].next = INVALID;
3019 (*_blossom_data)[blossom].pot = 0;
3020 (*_blossom_data)[blossom].offset = 0;
3023 for (EdgeIt e(_graph); e != INVALID; ++e) {
3024 int si = (*_node_index)[_graph.u(e)];
3025 int ti = (*_node_index)[_graph.v(e)];
3026 if (_graph.u(e) != _graph.v(e)) {
3027 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
3028 dualScale * _weight[e]) / 2);
3033 /// \brief Start the algorithm
3035 /// This function starts the algorithm.
3037 /// \pre \ref init() must be called before using this function.
3043 int unmatched = _node_num;
3044 while (unmatched > 0) {
3045 Value d2 = !_delta2->empty() ?
3046 _delta2->prio() : std::numeric_limits<Value>::max();
3048 Value d3 = !_delta3->empty() ?
3049 _delta3->prio() : std::numeric_limits<Value>::max();
3051 Value d4 = !_delta4->empty() ?
3052 _delta4->prio() : std::numeric_limits<Value>::max();
3054 _delta_sum = d2; OpType ot = D2;
3055 if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
3056 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
3058 if (_delta_sum == std::numeric_limits<Value>::max()) {
3065 int blossom = _delta2->top();
3066 Node n = _blossom_set->classTop(blossom);
3067 Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3073 Edge e = _delta3->top();
3075 int left_blossom = _blossom_set->find(_graph.u(e));
3076 int right_blossom = _blossom_set->find(_graph.v(e));
3078 if (left_blossom == right_blossom) {
3081 int left_tree = _tree_set->find(left_blossom);
3082 int right_tree = _tree_set->find(right_blossom);
3084 if (left_tree == right_tree) {
3085 shrinkOnEdge(e, left_tree);
3093 splitBlossom(_delta4->top());
3101 /// \brief Run the algorithm.
3103 /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
3105 /// \note mwpm.run() is just a shortcut of the following code.
3117 /// \name Primal Solution
3118 /// Functions to get the primal solution, i.e. the maximum weighted
3119 /// perfect matching.\n
3120 /// Either \ref run() or \ref start() function should be called before
3125 /// \brief Return the weight of the matching.
3127 /// This function returns the weight of the found matching.
3129 /// \pre Either run() or start() must be called before using this function.
3130 Value matchingWeight() const {
3132 for (NodeIt n(_graph); n != INVALID; ++n) {
3133 if ((*_matching)[n] != INVALID) {
3134 sum += _weight[(*_matching)[n]];
3140 /// \brief Return \c true if the given edge is in the matching.
3142 /// This function returns \c true if the given edge is in the found
3145 /// \pre Either run() or start() must be called before using this function.
3146 bool matching(const Edge& edge) const {
3147 return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
3150 /// \brief Return the matching arc (or edge) incident to the given node.
3152 /// This function returns the matching arc (or edge) incident to the
3153 /// given node in the found matching or \c INVALID if the node is
3154 /// not covered by the matching.
3156 /// \pre Either run() or start() must be called before using this function.
3157 Arc matching(const Node& node) const {
3158 return (*_matching)[node];
3161 /// \brief Return a const reference to the matching map.
3163 /// This function returns a const reference to a node map that stores
3164 /// the matching arc (or edge) incident to each node.
3165 const MatchingMap& matchingMap() const {
3169 /// \brief Return the mate of the given node.
3171 /// This function returns the mate of the given node in the found
3172 /// matching or \c INVALID if the node is not covered by the matching.
3174 /// \pre Either run() or start() must be called before using this function.
3175 Node mate(const Node& node) const {
3176 return _graph.target((*_matching)[node]);
3181 /// \name Dual Solution
3182 /// Functions to get the dual solution.\n
3183 /// Either \ref run() or \ref start() function should be called before
3188 /// \brief Return the value of the dual solution.
3190 /// This function returns the value of the dual solution.
3191 /// It should be equal to the primal value scaled by \ref dualScale
3194 /// \pre Either run() or start() must be called before using this function.
3195 Value dualValue() const {
3197 for (NodeIt n(_graph); n != INVALID; ++n) {
3198 sum += nodeValue(n);
3200 for (int i = 0; i < blossomNum(); ++i) {
3201 sum += blossomValue(i) * (blossomSize(i) / 2);
3206 /// \brief Return the dual value (potential) of the given node.
3208 /// This function returns the dual value (potential) of the given node.
3210 /// \pre Either run() or start() must be called before using this function.
3211 Value nodeValue(const Node& n) const {
3212 return (*_node_potential)[n];
3215 /// \brief Return the number of the blossoms in the basis.
3217 /// This function returns the number of the blossoms in the basis.
3219 /// \pre Either run() or start() must be called before using this function.
3221 int blossomNum() const {
3222 return _blossom_potential.size();
3225 /// \brief Return the number of the nodes in the given blossom.
3227 /// This function returns the number of the nodes in the given blossom.
3229 /// \pre Either run() or start() must be called before using this function.
3231 int blossomSize(int k) const {
3232 return _blossom_potential[k].end - _blossom_potential[k].begin;
3235 /// \brief Return the dual value (ptential) of the given blossom.
3237 /// This function returns the dual value (ptential) of the given blossom.
3239 /// \pre Either run() or start() must be called before using this function.
3240 Value blossomValue(int k) const {
3241 return _blossom_potential[k].value;
3244 /// \brief Iterator for obtaining the nodes of a blossom.
3246 /// This class provides an iterator for obtaining the nodes of the
3247 /// given blossom. It lists a subset of the nodes.
3248 /// Before using this iterator, you must allocate a
3249 /// MaxWeightedPerfectMatching class and execute it.
3253 /// \brief Constructor.
3255 /// Constructor to get the nodes of the given variable.
3257 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3258 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3259 /// must be called before initializing this iterator.
3260 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3261 : _algorithm(&algorithm)
3263 _index = _algorithm->_blossom_potential[variable].begin;
3264 _last = _algorithm->_blossom_potential[variable].end;
3267 /// \brief Conversion to \c Node.
3269 /// Conversion to \c Node.
3270 operator Node() const {
3271 return _algorithm->_blossom_node_list[_index];
3274 /// \brief Increment operator.
3276 /// Increment operator.
3277 BlossomIt& operator++() {
3282 /// \brief Validity checking
3284 /// This function checks whether the iterator is invalid.
3285 bool operator==(Invalid) const { return _index == _last; }
3287 /// \brief Validity checking
3289 /// This function checks whether the iterator is valid.
3290 bool operator!=(Invalid) const { return _index != _last; }
3293 const MaxWeightedPerfectMatching* _algorithm;
3302 } //END OF NAMESPACE LEMON
3304 #endif //LEMON_MAX_MATCHING_H