1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
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);
808 if (!_node_potential) {
809 _node_potential = new NodePotential(_graph);
812 _blossom_index = new IntNodeMap(_graph);
813 _blossom_set = new BlossomSet(*_blossom_index);
814 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
818 _node_index = new IntNodeMap(_graph);
819 _node_heap_index = new IntArcMap(_graph);
820 _node_data = new RangeMap<NodeData>(_node_num,
821 NodeData(*_node_heap_index));
825 _tree_set_index = new IntIntMap(_blossom_num);
826 _tree_set = new TreeSet(*_tree_set_index);
829 _delta1_index = new IntNodeMap(_graph);
830 _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
833 _delta2_index = new IntIntMap(_blossom_num);
834 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
837 _delta3_index = new IntEdgeMap(_graph);
838 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
841 _delta4_index = new IntIntMap(_blossom_num);
842 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
846 void destroyStructures() {
847 _node_num = countNodes(_graph);
848 _blossom_num = _node_num * 3 / 2;
853 if (_node_potential) {
854 delete _node_potential;
857 delete _blossom_index;
859 delete _blossom_data;
864 delete _node_heap_index;
869 delete _tree_set_index;
873 delete _delta1_index;
877 delete _delta2_index;
881 delete _delta3_index;
885 delete _delta4_index;
890 void matchedToEven(int blossom, int tree) {
891 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
892 _delta2->erase(blossom);
895 if (!_blossom_set->trivial(blossom)) {
896 (*_blossom_data)[blossom].pot -=
897 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
900 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
903 _blossom_set->increase(n, std::numeric_limits<Value>::max());
904 int ni = (*_node_index)[n];
906 (*_node_data)[ni].heap.clear();
907 (*_node_data)[ni].heap_index.clear();
909 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
911 _delta1->push(n, (*_node_data)[ni].pot);
913 for (InArcIt e(_graph, n); e != INVALID; ++e) {
914 Node v = _graph.source(e);
915 int vb = _blossom_set->find(v);
916 int vi = (*_node_index)[v];
918 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
919 dualScale * _weight[e];
921 if ((*_blossom_data)[vb].status == EVEN) {
922 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
923 _delta3->push(e, rw / 2);
925 } else if ((*_blossom_data)[vb].status == UNMATCHED) {
926 if (_delta3->state(e) != _delta3->IN_HEAP) {
927 _delta3->push(e, rw);
930 typename std::map<int, Arc>::iterator it =
931 (*_node_data)[vi].heap_index.find(tree);
933 if (it != (*_node_data)[vi].heap_index.end()) {
934 if ((*_node_data)[vi].heap[it->second] > rw) {
935 (*_node_data)[vi].heap.replace(it->second, e);
936 (*_node_data)[vi].heap.decrease(e, rw);
940 (*_node_data)[vi].heap.push(e, rw);
941 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
944 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
945 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
947 if ((*_blossom_data)[vb].status == MATCHED) {
948 if (_delta2->state(vb) != _delta2->IN_HEAP) {
949 _delta2->push(vb, _blossom_set->classPrio(vb) -
950 (*_blossom_data)[vb].offset);
951 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
952 (*_blossom_data)[vb].offset){
953 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
954 (*_blossom_data)[vb].offset);
961 (*_blossom_data)[blossom].offset = 0;
964 void matchedToOdd(int blossom) {
965 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
966 _delta2->erase(blossom);
968 (*_blossom_data)[blossom].offset += _delta_sum;
969 if (!_blossom_set->trivial(blossom)) {
970 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
971 (*_blossom_data)[blossom].offset);
975 void evenToMatched(int blossom, int tree) {
976 if (!_blossom_set->trivial(blossom)) {
977 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
980 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
982 int ni = (*_node_index)[n];
983 (*_node_data)[ni].pot -= _delta_sum;
987 for (InArcIt e(_graph, n); e != INVALID; ++e) {
988 Node v = _graph.source(e);
989 int vb = _blossom_set->find(v);
990 int vi = (*_node_index)[v];
992 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
993 dualScale * _weight[e];
996 if (_delta3->state(e) == _delta3->IN_HEAP) {
999 } else if ((*_blossom_data)[vb].status == EVEN) {
1001 if (_delta3->state(e) == _delta3->IN_HEAP) {
1005 int vt = _tree_set->find(vb);
1009 Arc r = _graph.oppositeArc(e);
1011 typename std::map<int, Arc>::iterator it =
1012 (*_node_data)[ni].heap_index.find(vt);
1014 if (it != (*_node_data)[ni].heap_index.end()) {
1015 if ((*_node_data)[ni].heap[it->second] > rw) {
1016 (*_node_data)[ni].heap.replace(it->second, r);
1017 (*_node_data)[ni].heap.decrease(r, rw);
1021 (*_node_data)[ni].heap.push(r, rw);
1022 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1025 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1026 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1028 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1029 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1030 (*_blossom_data)[blossom].offset);
1031 } else if ((*_delta2)[blossom] >
1032 _blossom_set->classPrio(blossom) -
1033 (*_blossom_data)[blossom].offset){
1034 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1035 (*_blossom_data)[blossom].offset);
1040 } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1041 if (_delta3->state(e) == _delta3->IN_HEAP) {
1046 typename std::map<int, Arc>::iterator it =
1047 (*_node_data)[vi].heap_index.find(tree);
1049 if (it != (*_node_data)[vi].heap_index.end()) {
1050 (*_node_data)[vi].heap.erase(it->second);
1051 (*_node_data)[vi].heap_index.erase(it);
1052 if ((*_node_data)[vi].heap.empty()) {
1053 _blossom_set->increase(v, std::numeric_limits<Value>::max());
1054 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
1055 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
1058 if ((*_blossom_data)[vb].status == MATCHED) {
1059 if (_blossom_set->classPrio(vb) ==
1060 std::numeric_limits<Value>::max()) {
1062 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
1063 (*_blossom_data)[vb].offset) {
1064 _delta2->increase(vb, _blossom_set->classPrio(vb) -
1065 (*_blossom_data)[vb].offset);
1074 void oddToMatched(int blossom) {
1075 (*_blossom_data)[blossom].offset -= _delta_sum;
1077 if (_blossom_set->classPrio(blossom) !=
1078 std::numeric_limits<Value>::max()) {
1079 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1080 (*_blossom_data)[blossom].offset);
1083 if (!_blossom_set->trivial(blossom)) {
1084 _delta4->erase(blossom);
1088 void oddToEven(int blossom, int tree) {
1089 if (!_blossom_set->trivial(blossom)) {
1090 _delta4->erase(blossom);
1091 (*_blossom_data)[blossom].pot -=
1092 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
1095 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1096 n != INVALID; ++n) {
1097 int ni = (*_node_index)[n];
1099 _blossom_set->increase(n, std::numeric_limits<Value>::max());
1101 (*_node_data)[ni].heap.clear();
1102 (*_node_data)[ni].heap_index.clear();
1103 (*_node_data)[ni].pot +=
1104 2 * _delta_sum - (*_blossom_data)[blossom].offset;
1106 _delta1->push(n, (*_node_data)[ni].pot);
1108 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1109 Node v = _graph.source(e);
1110 int vb = _blossom_set->find(v);
1111 int vi = (*_node_index)[v];
1113 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1114 dualScale * _weight[e];
1116 if ((*_blossom_data)[vb].status == EVEN) {
1117 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
1118 _delta3->push(e, rw / 2);
1120 } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1121 if (_delta3->state(e) != _delta3->IN_HEAP) {
1122 _delta3->push(e, rw);
1126 typename std::map<int, Arc>::iterator it =
1127 (*_node_data)[vi].heap_index.find(tree);
1129 if (it != (*_node_data)[vi].heap_index.end()) {
1130 if ((*_node_data)[vi].heap[it->second] > rw) {
1131 (*_node_data)[vi].heap.replace(it->second, e);
1132 (*_node_data)[vi].heap.decrease(e, rw);
1136 (*_node_data)[vi].heap.push(e, rw);
1137 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
1140 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
1141 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
1143 if ((*_blossom_data)[vb].status == MATCHED) {
1144 if (_delta2->state(vb) != _delta2->IN_HEAP) {
1145 _delta2->push(vb, _blossom_set->classPrio(vb) -
1146 (*_blossom_data)[vb].offset);
1147 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
1148 (*_blossom_data)[vb].offset) {
1149 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
1150 (*_blossom_data)[vb].offset);
1157 (*_blossom_data)[blossom].offset = 0;
1161 void matchedToUnmatched(int blossom) {
1162 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1163 _delta2->erase(blossom);
1166 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1167 n != INVALID; ++n) {
1168 int ni = (*_node_index)[n];
1170 _blossom_set->increase(n, std::numeric_limits<Value>::max());
1172 (*_node_data)[ni].heap.clear();
1173 (*_node_data)[ni].heap_index.clear();
1175 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1176 Node v = _graph.target(e);
1177 int vb = _blossom_set->find(v);
1178 int vi = (*_node_index)[v];
1180 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1181 dualScale * _weight[e];
1183 if ((*_blossom_data)[vb].status == EVEN) {
1184 if (_delta3->state(e) != _delta3->IN_HEAP) {
1185 _delta3->push(e, rw);
1192 void unmatchedToMatched(int blossom) {
1193 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
1194 n != INVALID; ++n) {
1195 int ni = (*_node_index)[n];
1197 for (InArcIt e(_graph, n); e != INVALID; ++e) {
1198 Node v = _graph.source(e);
1199 int vb = _blossom_set->find(v);
1200 int vi = (*_node_index)[v];
1202 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
1203 dualScale * _weight[e];
1205 if (vb == blossom) {
1206 if (_delta3->state(e) == _delta3->IN_HEAP) {
1209 } else if ((*_blossom_data)[vb].status == EVEN) {
1211 if (_delta3->state(e) == _delta3->IN_HEAP) {
1215 int vt = _tree_set->find(vb);
1217 Arc r = _graph.oppositeArc(e);
1219 typename std::map<int, Arc>::iterator it =
1220 (*_node_data)[ni].heap_index.find(vt);
1222 if (it != (*_node_data)[ni].heap_index.end()) {
1223 if ((*_node_data)[ni].heap[it->second] > rw) {
1224 (*_node_data)[ni].heap.replace(it->second, r);
1225 (*_node_data)[ni].heap.decrease(r, rw);
1229 (*_node_data)[ni].heap.push(r, rw);
1230 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
1233 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
1234 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
1236 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
1237 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
1238 (*_blossom_data)[blossom].offset);
1239 } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
1240 (*_blossom_data)[blossom].offset){
1241 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
1242 (*_blossom_data)[blossom].offset);
1246 } else if ((*_blossom_data)[vb].status == UNMATCHED) {
1247 if (_delta3->state(e) == _delta3->IN_HEAP) {
1255 void alternatePath(int even, int tree) {
1258 evenToMatched(even, tree);
1259 (*_blossom_data)[even].status = MATCHED;
1261 while ((*_blossom_data)[even].pred != INVALID) {
1262 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
1263 (*_blossom_data)[odd].status = MATCHED;
1265 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
1267 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
1268 (*_blossom_data)[even].status = MATCHED;
1269 evenToMatched(even, tree);
1270 (*_blossom_data)[even].next =
1271 _graph.oppositeArc((*_blossom_data)[odd].pred);
1276 void destroyTree(int tree) {
1277 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
1278 if ((*_blossom_data)[b].status == EVEN) {
1279 (*_blossom_data)[b].status = MATCHED;
1280 evenToMatched(b, tree);
1281 } else if ((*_blossom_data)[b].status == ODD) {
1282 (*_blossom_data)[b].status = MATCHED;
1286 _tree_set->eraseClass(tree);
1290 void unmatchNode(const Node& node) {
1291 int blossom = _blossom_set->find(node);
1292 int tree = _tree_set->find(blossom);
1294 alternatePath(blossom, tree);
1297 (*_blossom_data)[blossom].status = UNMATCHED;
1298 (*_blossom_data)[blossom].base = node;
1299 matchedToUnmatched(blossom);
1303 void augmentOnEdge(const Edge& edge) {
1305 int left = _blossom_set->find(_graph.u(edge));
1306 int right = _blossom_set->find(_graph.v(edge));
1308 if ((*_blossom_data)[left].status == EVEN) {
1309 int left_tree = _tree_set->find(left);
1310 alternatePath(left, left_tree);
1311 destroyTree(left_tree);
1313 (*_blossom_data)[left].status = MATCHED;
1314 unmatchedToMatched(left);
1317 if ((*_blossom_data)[right].status == EVEN) {
1318 int right_tree = _tree_set->find(right);
1319 alternatePath(right, right_tree);
1320 destroyTree(right_tree);
1322 (*_blossom_data)[right].status = MATCHED;
1323 unmatchedToMatched(right);
1326 (*_blossom_data)[left].next = _graph.direct(edge, true);
1327 (*_blossom_data)[right].next = _graph.direct(edge, false);
1330 void extendOnArc(const Arc& arc) {
1331 int base = _blossom_set->find(_graph.target(arc));
1332 int tree = _tree_set->find(base);
1334 int odd = _blossom_set->find(_graph.source(arc));
1335 _tree_set->insert(odd, tree);
1336 (*_blossom_data)[odd].status = ODD;
1338 (*_blossom_data)[odd].pred = arc;
1340 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
1341 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
1342 _tree_set->insert(even, tree);
1343 (*_blossom_data)[even].status = EVEN;
1344 matchedToEven(even, tree);
1347 void shrinkOnEdge(const Edge& edge, int tree) {
1349 std::vector<int> left_path, right_path;
1352 std::set<int> left_set, right_set;
1353 int left = _blossom_set->find(_graph.u(edge));
1354 left_path.push_back(left);
1355 left_set.insert(left);
1357 int right = _blossom_set->find(_graph.v(edge));
1358 right_path.push_back(right);
1359 right_set.insert(right);
1363 if ((*_blossom_data)[left].pred == INVALID) break;
1366 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1367 left_path.push_back(left);
1369 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
1370 left_path.push_back(left);
1372 left_set.insert(left);
1374 if (right_set.find(left) != right_set.end()) {
1379 if ((*_blossom_data)[right].pred == INVALID) break;
1382 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1383 right_path.push_back(right);
1385 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
1386 right_path.push_back(right);
1388 right_set.insert(right);
1390 if (left_set.find(right) != left_set.end()) {
1398 if ((*_blossom_data)[left].pred == INVALID) {
1400 while (left_set.find(nca) == left_set.end()) {
1402 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1403 right_path.push_back(nca);
1405 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1406 right_path.push_back(nca);
1410 while (right_set.find(nca) == right_set.end()) {
1412 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1413 left_path.push_back(nca);
1415 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
1416 left_path.push_back(nca);
1422 std::vector<int> subblossoms;
1425 prev = _graph.direct(edge, true);
1426 for (int i = 0; left_path[i] != nca; i += 2) {
1427 subblossoms.push_back(left_path[i]);
1428 (*_blossom_data)[left_path[i]].next = prev;
1429 _tree_set->erase(left_path[i]);
1431 subblossoms.push_back(left_path[i + 1]);
1432 (*_blossom_data)[left_path[i + 1]].status = EVEN;
1433 oddToEven(left_path[i + 1], tree);
1434 _tree_set->erase(left_path[i + 1]);
1435 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
1439 while (right_path[k] != nca) ++k;
1441 subblossoms.push_back(nca);
1442 (*_blossom_data)[nca].next = prev;
1444 for (int i = k - 2; i >= 0; i -= 2) {
1445 subblossoms.push_back(right_path[i + 1]);
1446 (*_blossom_data)[right_path[i + 1]].status = EVEN;
1447 oddToEven(right_path[i + 1], tree);
1448 _tree_set->erase(right_path[i + 1]);
1450 (*_blossom_data)[right_path[i + 1]].next =
1451 (*_blossom_data)[right_path[i + 1]].pred;
1453 subblossoms.push_back(right_path[i]);
1454 _tree_set->erase(right_path[i]);
1458 _blossom_set->join(subblossoms.begin(), subblossoms.end());
1460 for (int i = 0; i < int(subblossoms.size()); ++i) {
1461 if (!_blossom_set->trivial(subblossoms[i])) {
1462 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
1464 (*_blossom_data)[subblossoms[i]].status = MATCHED;
1467 (*_blossom_data)[surface].pot = -2 * _delta_sum;
1468 (*_blossom_data)[surface].offset = 0;
1469 (*_blossom_data)[surface].status = EVEN;
1470 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
1471 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
1473 _tree_set->insert(surface, tree);
1474 _tree_set->erase(nca);
1477 void splitBlossom(int blossom) {
1478 Arc next = (*_blossom_data)[blossom].next;
1479 Arc pred = (*_blossom_data)[blossom].pred;
1481 int tree = _tree_set->find(blossom);
1483 (*_blossom_data)[blossom].status = MATCHED;
1484 oddToMatched(blossom);
1485 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
1486 _delta2->erase(blossom);
1489 std::vector<int> subblossoms;
1490 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1492 Value offset = (*_blossom_data)[blossom].offset;
1493 int b = _blossom_set->find(_graph.source(pred));
1494 int d = _blossom_set->find(_graph.source(next));
1496 int ib = -1, id = -1;
1497 for (int i = 0; i < int(subblossoms.size()); ++i) {
1498 if (subblossoms[i] == b) ib = i;
1499 if (subblossoms[i] == d) id = i;
1501 (*_blossom_data)[subblossoms[i]].offset = offset;
1502 if (!_blossom_set->trivial(subblossoms[i])) {
1503 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
1505 if (_blossom_set->classPrio(subblossoms[i]) !=
1506 std::numeric_limits<Value>::max()) {
1507 _delta2->push(subblossoms[i],
1508 _blossom_set->classPrio(subblossoms[i]) -
1509 (*_blossom_data)[subblossoms[i]].offset);
1513 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
1514 for (int i = (id + 1) % subblossoms.size();
1515 i != ib; i = (i + 2) % subblossoms.size()) {
1516 int sb = subblossoms[i];
1517 int tb = subblossoms[(i + 1) % subblossoms.size()];
1518 (*_blossom_data)[sb].next =
1519 _graph.oppositeArc((*_blossom_data)[tb].next);
1522 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
1523 int sb = subblossoms[i];
1524 int tb = subblossoms[(i + 1) % subblossoms.size()];
1525 int ub = subblossoms[(i + 2) % subblossoms.size()];
1527 (*_blossom_data)[sb].status = ODD;
1529 _tree_set->insert(sb, tree);
1530 (*_blossom_data)[sb].pred = pred;
1531 (*_blossom_data)[sb].next =
1532 _graph.oppositeArc((*_blossom_data)[tb].next);
1534 pred = (*_blossom_data)[ub].next;
1536 (*_blossom_data)[tb].status = EVEN;
1537 matchedToEven(tb, tree);
1538 _tree_set->insert(tb, tree);
1539 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
1542 (*_blossom_data)[subblossoms[id]].status = ODD;
1543 matchedToOdd(subblossoms[id]);
1544 _tree_set->insert(subblossoms[id], tree);
1545 (*_blossom_data)[subblossoms[id]].next = next;
1546 (*_blossom_data)[subblossoms[id]].pred = pred;
1550 for (int i = (ib + 1) % subblossoms.size();
1551 i != id; i = (i + 2) % subblossoms.size()) {
1552 int sb = subblossoms[i];
1553 int tb = subblossoms[(i + 1) % subblossoms.size()];
1554 (*_blossom_data)[sb].next =
1555 _graph.oppositeArc((*_blossom_data)[tb].next);
1558 for (int i = id; i != ib; i = (i + 2) % subblossoms.size()) {
1559 int sb = subblossoms[i];
1560 int tb = subblossoms[(i + 1) % subblossoms.size()];
1561 int ub = subblossoms[(i + 2) % subblossoms.size()];
1563 (*_blossom_data)[sb].status = ODD;
1565 _tree_set->insert(sb, tree);
1566 (*_blossom_data)[sb].next = next;
1567 (*_blossom_data)[sb].pred =
1568 _graph.oppositeArc((*_blossom_data)[tb].next);
1570 (*_blossom_data)[tb].status = EVEN;
1571 matchedToEven(tb, tree);
1572 _tree_set->insert(tb, tree);
1573 (*_blossom_data)[tb].pred =
1574 (*_blossom_data)[tb].next =
1575 _graph.oppositeArc((*_blossom_data)[ub].next);
1576 next = (*_blossom_data)[ub].next;
1579 (*_blossom_data)[subblossoms[ib]].status = ODD;
1580 matchedToOdd(subblossoms[ib]);
1581 _tree_set->insert(subblossoms[ib], tree);
1582 (*_blossom_data)[subblossoms[ib]].next = next;
1583 (*_blossom_data)[subblossoms[ib]].pred = pred;
1585 _tree_set->erase(blossom);
1588 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
1589 if (_blossom_set->trivial(blossom)) {
1590 int bi = (*_node_index)[base];
1591 Value pot = (*_node_data)[bi].pot;
1593 (*_matching)[base] = matching;
1594 _blossom_node_list.push_back(base);
1595 (*_node_potential)[base] = pot;
1598 Value pot = (*_blossom_data)[blossom].pot;
1599 int bn = _blossom_node_list.size();
1601 std::vector<int> subblossoms;
1602 _blossom_set->split(blossom, std::back_inserter(subblossoms));
1603 int b = _blossom_set->find(base);
1605 for (int i = 0; i < int(subblossoms.size()); ++i) {
1606 if (subblossoms[i] == b) { ib = i; break; }
1609 for (int i = 1; i < int(subblossoms.size()); i += 2) {
1610 int sb = subblossoms[(ib + i) % subblossoms.size()];
1611 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
1613 Arc m = (*_blossom_data)[tb].next;
1614 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
1615 extractBlossom(tb, _graph.source(m), m);
1617 extractBlossom(subblossoms[ib], base, matching);
1619 int en = _blossom_node_list.size();
1621 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
1625 void extractMatching() {
1626 std::vector<int> blossoms;
1627 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
1628 blossoms.push_back(c);
1631 for (int i = 0; i < int(blossoms.size()); ++i) {
1632 if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
1634 Value offset = (*_blossom_data)[blossoms[i]].offset;
1635 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
1636 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
1637 n != INVALID; ++n) {
1638 (*_node_data)[(*_node_index)[n]].pot -= offset;
1641 Arc matching = (*_blossom_data)[blossoms[i]].next;
1642 Node base = _graph.source(matching);
1643 extractBlossom(blossoms[i], base, matching);
1645 Node base = (*_blossom_data)[blossoms[i]].base;
1646 extractBlossom(blossoms[i], base, INVALID);
1653 /// \brief Constructor
1656 MaxWeightedMatching(const Graph& graph, const WeightMap& weight)
1657 : _graph(graph), _weight(weight), _matching(0),
1658 _node_potential(0), _blossom_potential(), _blossom_node_list(),
1659 _node_num(0), _blossom_num(0),
1661 _blossom_index(0), _blossom_set(0), _blossom_data(0),
1662 _node_index(0), _node_heap_index(0), _node_data(0),
1663 _tree_set_index(0), _tree_set(0),
1665 _delta1_index(0), _delta1(0),
1666 _delta2_index(0), _delta2(0),
1667 _delta3_index(0), _delta3(0),
1668 _delta4_index(0), _delta4(0),
1672 ~MaxWeightedMatching() {
1673 destroyStructures();
1676 /// \name Execution Control
1677 /// The simplest way to execute the algorithm is to use the
1678 /// \ref run() member function.
1682 /// \brief Initialize the algorithm
1684 /// This function initializes the algorithm.
1688 for (ArcIt e(_graph); e != INVALID; ++e) {
1689 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
1691 for (NodeIt n(_graph); n != INVALID; ++n) {
1692 (*_delta1_index)[n] = _delta1->PRE_HEAP;
1694 for (EdgeIt e(_graph); e != INVALID; ++e) {
1695 (*_delta3_index)[e] = _delta3->PRE_HEAP;
1697 for (int i = 0; i < _blossom_num; ++i) {
1698 (*_delta2_index)[i] = _delta2->PRE_HEAP;
1699 (*_delta4_index)[i] = _delta4->PRE_HEAP;
1703 for (NodeIt n(_graph); n != INVALID; ++n) {
1705 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
1706 if (_graph.target(e) == n) continue;
1707 if ((dualScale * _weight[e]) / 2 > max) {
1708 max = (dualScale * _weight[e]) / 2;
1711 (*_node_index)[n] = index;
1712 (*_node_data)[index].pot = max;
1713 _delta1->push(n, max);
1715 _blossom_set->insert(n, std::numeric_limits<Value>::max());
1717 _tree_set->insert(blossom);
1719 (*_blossom_data)[blossom].status = EVEN;
1720 (*_blossom_data)[blossom].pred = INVALID;
1721 (*_blossom_data)[blossom].next = INVALID;
1722 (*_blossom_data)[blossom].pot = 0;
1723 (*_blossom_data)[blossom].offset = 0;
1726 for (EdgeIt e(_graph); e != INVALID; ++e) {
1727 int si = (*_node_index)[_graph.u(e)];
1728 int ti = (*_node_index)[_graph.v(e)];
1729 if (_graph.u(e) != _graph.v(e)) {
1730 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
1731 dualScale * _weight[e]) / 2);
1736 /// \brief Start the algorithm
1738 /// This function starts the algorithm.
1740 /// \pre \ref init() must be called before using this function.
1746 int unmatched = _node_num;
1747 while (unmatched > 0) {
1748 Value d1 = !_delta1->empty() ?
1749 _delta1->prio() : std::numeric_limits<Value>::max();
1751 Value d2 = !_delta2->empty() ?
1752 _delta2->prio() : std::numeric_limits<Value>::max();
1754 Value d3 = !_delta3->empty() ?
1755 _delta3->prio() : std::numeric_limits<Value>::max();
1757 Value d4 = !_delta4->empty() ?
1758 _delta4->prio() : std::numeric_limits<Value>::max();
1760 _delta_sum = d1; OpType ot = D1;
1761 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
1762 if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
1763 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
1769 Node n = _delta1->top();
1776 int blossom = _delta2->top();
1777 Node n = _blossom_set->classTop(blossom);
1778 Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
1784 Edge e = _delta3->top();
1786 int left_blossom = _blossom_set->find(_graph.u(e));
1787 int right_blossom = _blossom_set->find(_graph.v(e));
1789 if (left_blossom == right_blossom) {
1793 if ((*_blossom_data)[left_blossom].status == EVEN) {
1794 left_tree = _tree_set->find(left_blossom);
1800 if ((*_blossom_data)[right_blossom].status == EVEN) {
1801 right_tree = _tree_set->find(right_blossom);
1807 if (left_tree == right_tree) {
1808 shrinkOnEdge(e, left_tree);
1816 splitBlossom(_delta4->top());
1823 /// \brief Run the algorithm.
1825 /// This method runs the \c %MaxWeightedMatching algorithm.
1827 /// \note mwm.run() is just a shortcut of the following code.
1839 /// \name Primal Solution
1840 /// Functions to get the primal solution, i.e. the maximum weighted
1842 /// Either \ref run() or \ref start() function should be called before
1847 /// \brief Return the weight of the matching.
1849 /// This function returns the weight of the found matching.
1851 /// \pre Either run() or start() must be called before using this function.
1852 Value matchingWeight() const {
1854 for (NodeIt n(_graph); n != INVALID; ++n) {
1855 if ((*_matching)[n] != INVALID) {
1856 sum += _weight[(*_matching)[n]];
1862 /// \brief Return the size (cardinality) of the matching.
1864 /// This function returns the size (cardinality) of the found matching.
1866 /// \pre Either run() or start() must be called before using this function.
1867 int matchingSize() const {
1869 for (NodeIt n(_graph); n != INVALID; ++n) {
1870 if ((*_matching)[n] != INVALID) {
1877 /// \brief Return \c true if the given edge is in the matching.
1879 /// This function returns \c true if the given edge is in the found
1882 /// \pre Either run() or start() must be called before using this function.
1883 bool matching(const Edge& edge) const {
1884 return edge == (*_matching)[_graph.u(edge)];
1887 /// \brief Return the matching arc (or edge) incident to the given node.
1889 /// This function returns the matching arc (or edge) incident to the
1890 /// given node in the found matching or \c INVALID if the node is
1891 /// not covered by the matching.
1893 /// \pre Either run() or start() must be called before using this function.
1894 Arc matching(const Node& node) const {
1895 return (*_matching)[node];
1898 /// \brief Return a const reference to the matching map.
1900 /// This function returns a const reference to a node map that stores
1901 /// the matching arc (or edge) incident to each node.
1902 const MatchingMap& matchingMap() const {
1906 /// \brief Return the mate of the given node.
1908 /// This function returns the mate of the given node in the found
1909 /// matching or \c INVALID if the node is not covered by the matching.
1911 /// \pre Either run() or start() must be called before using this function.
1912 Node mate(const Node& node) const {
1913 return (*_matching)[node] != INVALID ?
1914 _graph.target((*_matching)[node]) : INVALID;
1919 /// \name Dual Solution
1920 /// Functions to get the dual solution.\n
1921 /// Either \ref run() or \ref start() function should be called before
1926 /// \brief Return the value of the dual solution.
1928 /// This function returns the value of the dual solution.
1929 /// It should be equal to the primal value scaled by \ref dualScale
1932 /// \pre Either run() or start() must be called before using this function.
1933 Value dualValue() const {
1935 for (NodeIt n(_graph); n != INVALID; ++n) {
1936 sum += nodeValue(n);
1938 for (int i = 0; i < blossomNum(); ++i) {
1939 sum += blossomValue(i) * (blossomSize(i) / 2);
1944 /// \brief Return the dual value (potential) of the given node.
1946 /// This function returns the dual value (potential) of the given node.
1948 /// \pre Either run() or start() must be called before using this function.
1949 Value nodeValue(const Node& n) const {
1950 return (*_node_potential)[n];
1953 /// \brief Return the number of the blossoms in the basis.
1955 /// This function returns the number of the blossoms in the basis.
1957 /// \pre Either run() or start() must be called before using this function.
1959 int blossomNum() const {
1960 return _blossom_potential.size();
1963 /// \brief Return the number of the nodes in the given blossom.
1965 /// This function returns the number of the nodes in the given blossom.
1967 /// \pre Either run() or start() must be called before using this function.
1969 int blossomSize(int k) const {
1970 return _blossom_potential[k].end - _blossom_potential[k].begin;
1973 /// \brief Return the dual value (ptential) of the given blossom.
1975 /// This function returns the dual value (ptential) of the given blossom.
1977 /// \pre Either run() or start() must be called before using this function.
1978 Value blossomValue(int k) const {
1979 return _blossom_potential[k].value;
1982 /// \brief Iterator for obtaining the nodes of a blossom.
1984 /// This class provides an iterator for obtaining the nodes of the
1985 /// given blossom. It lists a subset of the nodes.
1986 /// Before using this iterator, you must allocate a
1987 /// MaxWeightedMatching class and execute it.
1991 /// \brief Constructor.
1993 /// Constructor to get the nodes of the given variable.
1995 /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
1996 /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
1997 /// called before initializing this iterator.
1998 BlossomIt(const MaxWeightedMatching& algorithm, int variable)
1999 : _algorithm(&algorithm)
2001 _index = _algorithm->_blossom_potential[variable].begin;
2002 _last = _algorithm->_blossom_potential[variable].end;
2005 /// \brief Conversion to \c Node.
2007 /// Conversion to \c Node.
2008 operator Node() const {
2009 return _algorithm->_blossom_node_list[_index];
2012 /// \brief Increment operator.
2014 /// Increment operator.
2015 BlossomIt& operator++() {
2020 /// \brief Validity checking
2022 /// Checks whether the iterator is invalid.
2023 bool operator==(Invalid) const { return _index == _last; }
2025 /// \brief Validity checking
2027 /// Checks whether the iterator is valid.
2028 bool operator!=(Invalid) const { return _index != _last; }
2031 const MaxWeightedMatching* _algorithm;
2040 /// \ingroup matching
2042 /// \brief Weighted perfect matching in general graphs
2044 /// This class provides an efficient implementation of Edmond's
2045 /// maximum weighted perfect matching algorithm. The implementation
2046 /// is based on extensive use of priority queues and provides
2047 /// \f$O(nm\log n)\f$ time complexity.
2049 /// The maximum weighted perfect matching problem is to find a subset of
2050 /// the edges in an undirected graph with maximum overall weight for which
2051 /// each node has exactly one incident edge.
2052 /// It can be formulated with the following linear program.
2053 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
2054 /** \f[ \sum_{e \in \gamma(B)}x_e \le \frac{\vert B \vert - 1}{2}
2055 \quad \forall B\in\mathcal{O}\f] */
2056 /// \f[x_e \ge 0\quad \forall e\in E\f]
2057 /// \f[\max \sum_{e\in E}x_ew_e\f]
2058 /// where \f$\delta(X)\f$ is the set of edges incident to a node in
2059 /// \f$X\f$, \f$\gamma(X)\f$ is the set of edges with both ends in
2060 /// \f$X\f$ and \f$\mathcal{O}\f$ is the set of odd cardinality
2061 /// subsets of the nodes.
2063 /// The algorithm calculates an optimal matching and a proof of the
2064 /// optimality. The solution of the dual problem can be used to check
2065 /// the result of the algorithm. The dual linear problem is the
2067 /** \f[ y_u + y_v + \sum_{B \in \mathcal{O}, uv \in \gamma(B)}z_B \ge
2068 w_{uv} \quad \forall uv\in E\f] */
2069 /// \f[z_B \ge 0 \quad \forall B \in \mathcal{O}\f]
2070 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
2071 \frac{\vert B \vert - 1}{2}z_B\f] */
2073 /// The algorithm can be executed with the run() function.
2074 /// After it the matching (the primal solution) and the dual solution
2075 /// can be obtained using the query functions and the
2076 /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
2077 /// which is able to iterate on the nodes of a blossom.
2078 /// If the value type is integer, then the dual solution is multiplied
2079 /// by \ref MaxWeightedMatching::dualScale "4".
2081 /// \tparam GR The undirected graph type the algorithm runs on.
2082 /// \tparam WM The type edge weight map. The default type is
2083 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
2085 template <typename GR, typename WM>
2087 template <typename GR,
2088 typename WM = typename GR::template EdgeMap<int> >
2090 class MaxWeightedPerfectMatching {
2093 /// The graph type of the algorithm
2095 /// The type of the edge weight map
2096 typedef WM WeightMap;
2097 /// The value type of the edge weights
2098 typedef typename WeightMap::Value Value;
2100 /// \brief Scaling factor for dual solution
2102 /// Scaling factor for dual solution, it is equal to 4 or 1
2103 /// according to the value type.
2104 static const int dualScale =
2105 std::numeric_limits<Value>::is_integer ? 4 : 1;
2107 /// The type of the matching map
2108 typedef typename Graph::template NodeMap<typename Graph::Arc>
2113 TEMPLATE_GRAPH_TYPEDEFS(Graph);
2115 typedef typename Graph::template NodeMap<Value> NodePotential;
2116 typedef std::vector<Node> BlossomNodeList;
2118 struct BlossomVariable {
2122 BlossomVariable(int _begin, int _end, Value _value)
2123 : begin(_begin), end(_end), value(_value) {}
2127 typedef std::vector<BlossomVariable> BlossomPotential;
2129 const Graph& _graph;
2130 const WeightMap& _weight;
2132 MatchingMap* _matching;
2134 NodePotential* _node_potential;
2136 BlossomPotential _blossom_potential;
2137 BlossomNodeList _blossom_node_list;
2142 typedef RangeMap<int> IntIntMap;
2145 EVEN = -1, MATCHED = 0, ODD = 1
2148 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
2149 struct BlossomData {
2156 IntNodeMap *_blossom_index;
2157 BlossomSet *_blossom_set;
2158 RangeMap<BlossomData>* _blossom_data;
2160 IntNodeMap *_node_index;
2161 IntArcMap *_node_heap_index;
2165 NodeData(IntArcMap& node_heap_index)
2166 : heap(node_heap_index) {}
2170 BinHeap<Value, IntArcMap> heap;
2171 std::map<int, Arc> heap_index;
2176 RangeMap<NodeData>* _node_data;
2178 typedef ExtendFindEnum<IntIntMap> TreeSet;
2180 IntIntMap *_tree_set_index;
2183 IntIntMap *_delta2_index;
2184 BinHeap<Value, IntIntMap> *_delta2;
2186 IntEdgeMap *_delta3_index;
2187 BinHeap<Value, IntEdgeMap> *_delta3;
2189 IntIntMap *_delta4_index;
2190 BinHeap<Value, IntIntMap> *_delta4;
2194 void createStructures() {
2195 _node_num = countNodes(_graph);
2196 _blossom_num = _node_num * 3 / 2;
2199 _matching = new MatchingMap(_graph);
2201 if (!_node_potential) {
2202 _node_potential = new NodePotential(_graph);
2204 if (!_blossom_set) {
2205 _blossom_index = new IntNodeMap(_graph);
2206 _blossom_set = new BlossomSet(*_blossom_index);
2207 _blossom_data = new RangeMap<BlossomData>(_blossom_num);
2211 _node_index = new IntNodeMap(_graph);
2212 _node_heap_index = new IntArcMap(_graph);
2213 _node_data = new RangeMap<NodeData>(_node_num,
2214 NodeData(*_node_heap_index));
2218 _tree_set_index = new IntIntMap(_blossom_num);
2219 _tree_set = new TreeSet(*_tree_set_index);
2222 _delta2_index = new IntIntMap(_blossom_num);
2223 _delta2 = new BinHeap<Value, IntIntMap>(*_delta2_index);
2226 _delta3_index = new IntEdgeMap(_graph);
2227 _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
2230 _delta4_index = new IntIntMap(_blossom_num);
2231 _delta4 = new BinHeap<Value, IntIntMap>(*_delta4_index);
2235 void destroyStructures() {
2236 _node_num = countNodes(_graph);
2237 _blossom_num = _node_num * 3 / 2;
2242 if (_node_potential) {
2243 delete _node_potential;
2246 delete _blossom_index;
2247 delete _blossom_set;
2248 delete _blossom_data;
2253 delete _node_heap_index;
2258 delete _tree_set_index;
2262 delete _delta2_index;
2266 delete _delta3_index;
2270 delete _delta4_index;
2275 void matchedToEven(int blossom, int tree) {
2276 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2277 _delta2->erase(blossom);
2280 if (!_blossom_set->trivial(blossom)) {
2281 (*_blossom_data)[blossom].pot -=
2282 2 * (_delta_sum - (*_blossom_data)[blossom].offset);
2285 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2286 n != INVALID; ++n) {
2288 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2289 int ni = (*_node_index)[n];
2291 (*_node_data)[ni].heap.clear();
2292 (*_node_data)[ni].heap_index.clear();
2294 (*_node_data)[ni].pot += _delta_sum - (*_blossom_data)[blossom].offset;
2296 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2297 Node v = _graph.source(e);
2298 int vb = _blossom_set->find(v);
2299 int vi = (*_node_index)[v];
2301 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2302 dualScale * _weight[e];
2304 if ((*_blossom_data)[vb].status == EVEN) {
2305 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2306 _delta3->push(e, rw / 2);
2309 typename std::map<int, Arc>::iterator it =
2310 (*_node_data)[vi].heap_index.find(tree);
2312 if (it != (*_node_data)[vi].heap_index.end()) {
2313 if ((*_node_data)[vi].heap[it->second] > rw) {
2314 (*_node_data)[vi].heap.replace(it->second, e);
2315 (*_node_data)[vi].heap.decrease(e, rw);
2319 (*_node_data)[vi].heap.push(e, rw);
2320 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2323 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2324 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2326 if ((*_blossom_data)[vb].status == MATCHED) {
2327 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2328 _delta2->push(vb, _blossom_set->classPrio(vb) -
2329 (*_blossom_data)[vb].offset);
2330 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2331 (*_blossom_data)[vb].offset){
2332 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2333 (*_blossom_data)[vb].offset);
2340 (*_blossom_data)[blossom].offset = 0;
2343 void matchedToOdd(int blossom) {
2344 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2345 _delta2->erase(blossom);
2347 (*_blossom_data)[blossom].offset += _delta_sum;
2348 if (!_blossom_set->trivial(blossom)) {
2349 _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
2350 (*_blossom_data)[blossom].offset);
2354 void evenToMatched(int blossom, int tree) {
2355 if (!_blossom_set->trivial(blossom)) {
2356 (*_blossom_data)[blossom].pot += 2 * _delta_sum;
2359 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2360 n != INVALID; ++n) {
2361 int ni = (*_node_index)[n];
2362 (*_node_data)[ni].pot -= _delta_sum;
2364 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2365 Node v = _graph.source(e);
2366 int vb = _blossom_set->find(v);
2367 int vi = (*_node_index)[v];
2369 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2370 dualScale * _weight[e];
2372 if (vb == blossom) {
2373 if (_delta3->state(e) == _delta3->IN_HEAP) {
2376 } else if ((*_blossom_data)[vb].status == EVEN) {
2378 if (_delta3->state(e) == _delta3->IN_HEAP) {
2382 int vt = _tree_set->find(vb);
2386 Arc r = _graph.oppositeArc(e);
2388 typename std::map<int, Arc>::iterator it =
2389 (*_node_data)[ni].heap_index.find(vt);
2391 if (it != (*_node_data)[ni].heap_index.end()) {
2392 if ((*_node_data)[ni].heap[it->second] > rw) {
2393 (*_node_data)[ni].heap.replace(it->second, r);
2394 (*_node_data)[ni].heap.decrease(r, rw);
2398 (*_node_data)[ni].heap.push(r, rw);
2399 (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
2402 if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
2403 _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
2405 if (_delta2->state(blossom) != _delta2->IN_HEAP) {
2406 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2407 (*_blossom_data)[blossom].offset);
2408 } else if ((*_delta2)[blossom] >
2409 _blossom_set->classPrio(blossom) -
2410 (*_blossom_data)[blossom].offset){
2411 _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
2412 (*_blossom_data)[blossom].offset);
2418 typename std::map<int, Arc>::iterator it =
2419 (*_node_data)[vi].heap_index.find(tree);
2421 if (it != (*_node_data)[vi].heap_index.end()) {
2422 (*_node_data)[vi].heap.erase(it->second);
2423 (*_node_data)[vi].heap_index.erase(it);
2424 if ((*_node_data)[vi].heap.empty()) {
2425 _blossom_set->increase(v, std::numeric_limits<Value>::max());
2426 } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
2427 _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
2430 if ((*_blossom_data)[vb].status == MATCHED) {
2431 if (_blossom_set->classPrio(vb) ==
2432 std::numeric_limits<Value>::max()) {
2434 } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
2435 (*_blossom_data)[vb].offset) {
2436 _delta2->increase(vb, _blossom_set->classPrio(vb) -
2437 (*_blossom_data)[vb].offset);
2446 void oddToMatched(int blossom) {
2447 (*_blossom_data)[blossom].offset -= _delta_sum;
2449 if (_blossom_set->classPrio(blossom) !=
2450 std::numeric_limits<Value>::max()) {
2451 _delta2->push(blossom, _blossom_set->classPrio(blossom) -
2452 (*_blossom_data)[blossom].offset);
2455 if (!_blossom_set->trivial(blossom)) {
2456 _delta4->erase(blossom);
2460 void oddToEven(int blossom, int tree) {
2461 if (!_blossom_set->trivial(blossom)) {
2462 _delta4->erase(blossom);
2463 (*_blossom_data)[blossom].pot -=
2464 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
2467 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
2468 n != INVALID; ++n) {
2469 int ni = (*_node_index)[n];
2471 _blossom_set->increase(n, std::numeric_limits<Value>::max());
2473 (*_node_data)[ni].heap.clear();
2474 (*_node_data)[ni].heap_index.clear();
2475 (*_node_data)[ni].pot +=
2476 2 * _delta_sum - (*_blossom_data)[blossom].offset;
2478 for (InArcIt e(_graph, n); e != INVALID; ++e) {
2479 Node v = _graph.source(e);
2480 int vb = _blossom_set->find(v);
2481 int vi = (*_node_index)[v];
2483 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
2484 dualScale * _weight[e];
2486 if ((*_blossom_data)[vb].status == EVEN) {
2487 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
2488 _delta3->push(e, rw / 2);
2492 typename std::map<int, Arc>::iterator it =
2493 (*_node_data)[vi].heap_index.find(tree);
2495 if (it != (*_node_data)[vi].heap_index.end()) {
2496 if ((*_node_data)[vi].heap[it->second] > rw) {
2497 (*_node_data)[vi].heap.replace(it->second, e);
2498 (*_node_data)[vi].heap.decrease(e, rw);
2502 (*_node_data)[vi].heap.push(e, rw);
2503 (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
2506 if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
2507 _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
2509 if ((*_blossom_data)[vb].status == MATCHED) {
2510 if (_delta2->state(vb) != _delta2->IN_HEAP) {
2511 _delta2->push(vb, _blossom_set->classPrio(vb) -
2512 (*_blossom_data)[vb].offset);
2513 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
2514 (*_blossom_data)[vb].offset) {
2515 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
2516 (*_blossom_data)[vb].offset);
2523 (*_blossom_data)[blossom].offset = 0;
2526 void alternatePath(int even, int tree) {
2529 evenToMatched(even, tree);
2530 (*_blossom_data)[even].status = MATCHED;
2532 while ((*_blossom_data)[even].pred != INVALID) {
2533 odd = _blossom_set->find(_graph.target((*_blossom_data)[even].pred));
2534 (*_blossom_data)[odd].status = MATCHED;
2536 (*_blossom_data)[odd].next = (*_blossom_data)[odd].pred;
2538 even = _blossom_set->find(_graph.target((*_blossom_data)[odd].pred));
2539 (*_blossom_data)[even].status = MATCHED;
2540 evenToMatched(even, tree);
2541 (*_blossom_data)[even].next =
2542 _graph.oppositeArc((*_blossom_data)[odd].pred);
2547 void destroyTree(int tree) {
2548 for (TreeSet::ItemIt b(*_tree_set, tree); b != INVALID; ++b) {
2549 if ((*_blossom_data)[b].status == EVEN) {
2550 (*_blossom_data)[b].status = MATCHED;
2551 evenToMatched(b, tree);
2552 } else if ((*_blossom_data)[b].status == ODD) {
2553 (*_blossom_data)[b].status = MATCHED;
2557 _tree_set->eraseClass(tree);
2560 void augmentOnEdge(const Edge& edge) {
2562 int left = _blossom_set->find(_graph.u(edge));
2563 int right = _blossom_set->find(_graph.v(edge));
2565 int left_tree = _tree_set->find(left);
2566 alternatePath(left, left_tree);
2567 destroyTree(left_tree);
2569 int right_tree = _tree_set->find(right);
2570 alternatePath(right, right_tree);
2571 destroyTree(right_tree);
2573 (*_blossom_data)[left].next = _graph.direct(edge, true);
2574 (*_blossom_data)[right].next = _graph.direct(edge, false);
2577 void extendOnArc(const Arc& arc) {
2578 int base = _blossom_set->find(_graph.target(arc));
2579 int tree = _tree_set->find(base);
2581 int odd = _blossom_set->find(_graph.source(arc));
2582 _tree_set->insert(odd, tree);
2583 (*_blossom_data)[odd].status = ODD;
2585 (*_blossom_data)[odd].pred = arc;
2587 int even = _blossom_set->find(_graph.target((*_blossom_data)[odd].next));
2588 (*_blossom_data)[even].pred = (*_blossom_data)[even].next;
2589 _tree_set->insert(even, tree);
2590 (*_blossom_data)[even].status = EVEN;
2591 matchedToEven(even, tree);
2594 void shrinkOnEdge(const Edge& edge, int tree) {
2596 std::vector<int> left_path, right_path;
2599 std::set<int> left_set, right_set;
2600 int left = _blossom_set->find(_graph.u(edge));
2601 left_path.push_back(left);
2602 left_set.insert(left);
2604 int right = _blossom_set->find(_graph.v(edge));
2605 right_path.push_back(right);
2606 right_set.insert(right);
2610 if ((*_blossom_data)[left].pred == INVALID) break;
2613 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2614 left_path.push_back(left);
2616 _blossom_set->find(_graph.target((*_blossom_data)[left].pred));
2617 left_path.push_back(left);
2619 left_set.insert(left);
2621 if (right_set.find(left) != right_set.end()) {
2626 if ((*_blossom_data)[right].pred == INVALID) break;
2629 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2630 right_path.push_back(right);
2632 _blossom_set->find(_graph.target((*_blossom_data)[right].pred));
2633 right_path.push_back(right);
2635 right_set.insert(right);
2637 if (left_set.find(right) != left_set.end()) {
2645 if ((*_blossom_data)[left].pred == INVALID) {
2647 while (left_set.find(nca) == left_set.end()) {
2649 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2650 right_path.push_back(nca);
2652 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2653 right_path.push_back(nca);
2657 while (right_set.find(nca) == right_set.end()) {
2659 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2660 left_path.push_back(nca);
2662 _blossom_set->find(_graph.target((*_blossom_data)[nca].pred));
2663 left_path.push_back(nca);
2669 std::vector<int> subblossoms;
2672 prev = _graph.direct(edge, true);
2673 for (int i = 0; left_path[i] != nca; i += 2) {
2674 subblossoms.push_back(left_path[i]);
2675 (*_blossom_data)[left_path[i]].next = prev;
2676 _tree_set->erase(left_path[i]);
2678 subblossoms.push_back(left_path[i + 1]);
2679 (*_blossom_data)[left_path[i + 1]].status = EVEN;
2680 oddToEven(left_path[i + 1], tree);
2681 _tree_set->erase(left_path[i + 1]);
2682 prev = _graph.oppositeArc((*_blossom_data)[left_path[i + 1]].pred);
2686 while (right_path[k] != nca) ++k;
2688 subblossoms.push_back(nca);
2689 (*_blossom_data)[nca].next = prev;
2691 for (int i = k - 2; i >= 0; i -= 2) {
2692 subblossoms.push_back(right_path[i + 1]);
2693 (*_blossom_data)[right_path[i + 1]].status = EVEN;
2694 oddToEven(right_path[i + 1], tree);
2695 _tree_set->erase(right_path[i + 1]);
2697 (*_blossom_data)[right_path[i + 1]].next =
2698 (*_blossom_data)[right_path[i + 1]].pred;
2700 subblossoms.push_back(right_path[i]);
2701 _tree_set->erase(right_path[i]);
2705 _blossom_set->join(subblossoms.begin(), subblossoms.end());
2707 for (int i = 0; i < int(subblossoms.size()); ++i) {
2708 if (!_blossom_set->trivial(subblossoms[i])) {
2709 (*_blossom_data)[subblossoms[i]].pot += 2 * _delta_sum;
2711 (*_blossom_data)[subblossoms[i]].status = MATCHED;
2714 (*_blossom_data)[surface].pot = -2 * _delta_sum;
2715 (*_blossom_data)[surface].offset = 0;
2716 (*_blossom_data)[surface].status = EVEN;
2717 (*_blossom_data)[surface].pred = (*_blossom_data)[nca].pred;
2718 (*_blossom_data)[surface].next = (*_blossom_data)[nca].pred;
2720 _tree_set->insert(surface, tree);
2721 _tree_set->erase(nca);
2724 void splitBlossom(int blossom) {
2725 Arc next = (*_blossom_data)[blossom].next;
2726 Arc pred = (*_blossom_data)[blossom].pred;
2728 int tree = _tree_set->find(blossom);
2730 (*_blossom_data)[blossom].status = MATCHED;
2731 oddToMatched(blossom);
2732 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
2733 _delta2->erase(blossom);
2736 std::vector<int> subblossoms;
2737 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2739 Value offset = (*_blossom_data)[blossom].offset;
2740 int b = _blossom_set->find(_graph.source(pred));
2741 int d = _blossom_set->find(_graph.source(next));
2743 int ib = -1, id = -1;
2744 for (int i = 0; i < int(subblossoms.size()); ++i) {
2745 if (subblossoms[i] == b) ib = i;
2746 if (subblossoms[i] == d) id = i;
2748 (*_blossom_data)[subblossoms[i]].offset = offset;
2749 if (!_blossom_set->trivial(subblossoms[i])) {
2750 (*_blossom_data)[subblossoms[i]].pot -= 2 * offset;
2752 if (_blossom_set->classPrio(subblossoms[i]) !=
2753 std::numeric_limits<Value>::max()) {
2754 _delta2->push(subblossoms[i],
2755 _blossom_set->classPrio(subblossoms[i]) -
2756 (*_blossom_data)[subblossoms[i]].offset);
2760 if (id > ib ? ((id - ib) % 2 == 0) : ((ib - id) % 2 == 1)) {
2761 for (int i = (id + 1) % subblossoms.size();
2762 i != ib; i = (i + 2) % subblossoms.size()) {
2763 int sb = subblossoms[i];
2764 int tb = subblossoms[(i + 1) % subblossoms.size()];
2765 (*_blossom_data)[sb].next =
2766 _graph.oppositeArc((*_blossom_data)[tb].next);
2769 for (int i = ib; i != id; i = (i + 2) % subblossoms.size()) {
2770 int sb = subblossoms[i];
2771 int tb = subblossoms[(i + 1) % subblossoms.size()];
2772 int ub = subblossoms[(i + 2) % subblossoms.size()];
2774 (*_blossom_data)[sb].status = ODD;
2776 _tree_set->insert(sb, tree);
2777 (*_blossom_data)[sb].pred = pred;
2778 (*_blossom_data)[sb].next =
2779 _graph.oppositeArc((*_blossom_data)[tb].next);
2781 pred = (*_blossom_data)[ub].next;
2783 (*_blossom_data)[tb].status = EVEN;
2784 matchedToEven(tb, tree);
2785 _tree_set->insert(tb, tree);
2786 (*_blossom_data)[tb].pred = (*_blossom_data)[tb].next;
2789 (*_blossom_data)[subblossoms[id]].status = ODD;
2790 matchedToOdd(subblossoms[id]);
2791 _tree_set->insert(subblossoms[id], tree);
2792 (*_blossom_data)[subblossoms[id]].next = next;
2793 (*_blossom_data)[subblossoms[id]].pred = pred;
2797 for (int i = (ib + 1) % subblossoms.size();
2798 i != id; 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);
2805 for (int i = id; i != ib; 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()];
2810 (*_blossom_data)[sb].status = ODD;
2812 _tree_set->insert(sb, tree);
2813 (*_blossom_data)[sb].next = next;
2814 (*_blossom_data)[sb].pred =
2815 _graph.oppositeArc((*_blossom_data)[tb].next);
2817 (*_blossom_data)[tb].status = EVEN;
2818 matchedToEven(tb, tree);
2819 _tree_set->insert(tb, tree);
2820 (*_blossom_data)[tb].pred =
2821 (*_blossom_data)[tb].next =
2822 _graph.oppositeArc((*_blossom_data)[ub].next);
2823 next = (*_blossom_data)[ub].next;
2826 (*_blossom_data)[subblossoms[ib]].status = ODD;
2827 matchedToOdd(subblossoms[ib]);
2828 _tree_set->insert(subblossoms[ib], tree);
2829 (*_blossom_data)[subblossoms[ib]].next = next;
2830 (*_blossom_data)[subblossoms[ib]].pred = pred;
2832 _tree_set->erase(blossom);
2835 void extractBlossom(int blossom, const Node& base, const Arc& matching) {
2836 if (_blossom_set->trivial(blossom)) {
2837 int bi = (*_node_index)[base];
2838 Value pot = (*_node_data)[bi].pot;
2840 (*_matching)[base] = matching;
2841 _blossom_node_list.push_back(base);
2842 (*_node_potential)[base] = pot;
2845 Value pot = (*_blossom_data)[blossom].pot;
2846 int bn = _blossom_node_list.size();
2848 std::vector<int> subblossoms;
2849 _blossom_set->split(blossom, std::back_inserter(subblossoms));
2850 int b = _blossom_set->find(base);
2852 for (int i = 0; i < int(subblossoms.size()); ++i) {
2853 if (subblossoms[i] == b) { ib = i; break; }
2856 for (int i = 1; i < int(subblossoms.size()); i += 2) {
2857 int sb = subblossoms[(ib + i) % subblossoms.size()];
2858 int tb = subblossoms[(ib + i + 1) % subblossoms.size()];
2860 Arc m = (*_blossom_data)[tb].next;
2861 extractBlossom(sb, _graph.target(m), _graph.oppositeArc(m));
2862 extractBlossom(tb, _graph.source(m), m);
2864 extractBlossom(subblossoms[ib], base, matching);
2866 int en = _blossom_node_list.size();
2868 _blossom_potential.push_back(BlossomVariable(bn, en, pot));
2872 void extractMatching() {
2873 std::vector<int> blossoms;
2874 for (typename BlossomSet::ClassIt c(*_blossom_set); c != INVALID; ++c) {
2875 blossoms.push_back(c);
2878 for (int i = 0; i < int(blossoms.size()); ++i) {
2880 Value offset = (*_blossom_data)[blossoms[i]].offset;
2881 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
2882 for (typename BlossomSet::ItemIt n(*_blossom_set, blossoms[i]);
2883 n != INVALID; ++n) {
2884 (*_node_data)[(*_node_index)[n]].pot -= offset;
2887 Arc matching = (*_blossom_data)[blossoms[i]].next;
2888 Node base = _graph.source(matching);
2889 extractBlossom(blossoms[i], base, matching);
2895 /// \brief Constructor
2898 MaxWeightedPerfectMatching(const Graph& graph, const WeightMap& weight)
2899 : _graph(graph), _weight(weight), _matching(0),
2900 _node_potential(0), _blossom_potential(), _blossom_node_list(),
2901 _node_num(0), _blossom_num(0),
2903 _blossom_index(0), _blossom_set(0), _blossom_data(0),
2904 _node_index(0), _node_heap_index(0), _node_data(0),
2905 _tree_set_index(0), _tree_set(0),
2907 _delta2_index(0), _delta2(0),
2908 _delta3_index(0), _delta3(0),
2909 _delta4_index(0), _delta4(0),
2913 ~MaxWeightedPerfectMatching() {
2914 destroyStructures();
2917 /// \name Execution Control
2918 /// The simplest way to execute the algorithm is to use the
2919 /// \ref run() member function.
2923 /// \brief Initialize the algorithm
2925 /// This function initializes the algorithm.
2929 for (ArcIt e(_graph); e != INVALID; ++e) {
2930 (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
2932 for (EdgeIt e(_graph); e != INVALID; ++e) {
2933 (*_delta3_index)[e] = _delta3->PRE_HEAP;
2935 for (int i = 0; i < _blossom_num; ++i) {
2936 (*_delta2_index)[i] = _delta2->PRE_HEAP;
2937 (*_delta4_index)[i] = _delta4->PRE_HEAP;
2941 for (NodeIt n(_graph); n != INVALID; ++n) {
2942 Value max = - std::numeric_limits<Value>::max();
2943 for (OutArcIt e(_graph, n); e != INVALID; ++e) {
2944 if (_graph.target(e) == n) continue;
2945 if ((dualScale * _weight[e]) / 2 > max) {
2946 max = (dualScale * _weight[e]) / 2;
2949 (*_node_index)[n] = index;
2950 (*_node_data)[index].pot = max;
2952 _blossom_set->insert(n, std::numeric_limits<Value>::max());
2954 _tree_set->insert(blossom);
2956 (*_blossom_data)[blossom].status = EVEN;
2957 (*_blossom_data)[blossom].pred = INVALID;
2958 (*_blossom_data)[blossom].next = INVALID;
2959 (*_blossom_data)[blossom].pot = 0;
2960 (*_blossom_data)[blossom].offset = 0;
2963 for (EdgeIt e(_graph); e != INVALID; ++e) {
2964 int si = (*_node_index)[_graph.u(e)];
2965 int ti = (*_node_index)[_graph.v(e)];
2966 if (_graph.u(e) != _graph.v(e)) {
2967 _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
2968 dualScale * _weight[e]) / 2);
2973 /// \brief Start the algorithm
2975 /// This function starts the algorithm.
2977 /// \pre \ref init() must be called before using this function.
2983 int unmatched = _node_num;
2984 while (unmatched > 0) {
2985 Value d2 = !_delta2->empty() ?
2986 _delta2->prio() : std::numeric_limits<Value>::max();
2988 Value d3 = !_delta3->empty() ?
2989 _delta3->prio() : std::numeric_limits<Value>::max();
2991 Value d4 = !_delta4->empty() ?
2992 _delta4->prio() : std::numeric_limits<Value>::max();
2994 _delta_sum = d2; OpType ot = D2;
2995 if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
2996 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
2998 if (_delta_sum == std::numeric_limits<Value>::max()) {
3005 int blossom = _delta2->top();
3006 Node n = _blossom_set->classTop(blossom);
3007 Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
3013 Edge e = _delta3->top();
3015 int left_blossom = _blossom_set->find(_graph.u(e));
3016 int right_blossom = _blossom_set->find(_graph.v(e));
3018 if (left_blossom == right_blossom) {
3021 int left_tree = _tree_set->find(left_blossom);
3022 int right_tree = _tree_set->find(right_blossom);
3024 if (left_tree == right_tree) {
3025 shrinkOnEdge(e, left_tree);
3033 splitBlossom(_delta4->top());
3041 /// \brief Run the algorithm.
3043 /// This method runs the \c %MaxWeightedPerfectMatching algorithm.
3045 /// \note mwpm.run() is just a shortcut of the following code.
3057 /// \name Primal Solution
3058 /// Functions to get the primal solution, i.e. the maximum weighted
3059 /// perfect matching.\n
3060 /// Either \ref run() or \ref start() function should be called before
3065 /// \brief Return the weight of the matching.
3067 /// This function returns the weight of the found matching.
3069 /// \pre Either run() or start() must be called before using this function.
3070 Value matchingWeight() const {
3072 for (NodeIt n(_graph); n != INVALID; ++n) {
3073 if ((*_matching)[n] != INVALID) {
3074 sum += _weight[(*_matching)[n]];
3080 /// \brief Return \c true if the given edge is in the matching.
3082 /// This function returns \c true if the given edge is in the found
3085 /// \pre Either run() or start() must be called before using this function.
3086 bool matching(const Edge& edge) const {
3087 return static_cast<const Edge&>((*_matching)[_graph.u(edge)]) == edge;
3090 /// \brief Return the matching arc (or edge) incident to the given node.
3092 /// This function returns the matching arc (or edge) incident to the
3093 /// given node in the found matching or \c INVALID if the node is
3094 /// not covered by the matching.
3096 /// \pre Either run() or start() must be called before using this function.
3097 Arc matching(const Node& node) const {
3098 return (*_matching)[node];
3101 /// \brief Return a const reference to the matching map.
3103 /// This function returns a const reference to a node map that stores
3104 /// the matching arc (or edge) incident to each node.
3105 const MatchingMap& matchingMap() const {
3109 /// \brief Return the mate of the given node.
3111 /// This function returns the mate of the given node in the found
3112 /// matching or \c INVALID if the node is not covered by the matching.
3114 /// \pre Either run() or start() must be called before using this function.
3115 Node mate(const Node& node) const {
3116 return _graph.target((*_matching)[node]);
3121 /// \name Dual Solution
3122 /// Functions to get the dual solution.\n
3123 /// Either \ref run() or \ref start() function should be called before
3128 /// \brief Return the value of the dual solution.
3130 /// This function returns the value of the dual solution.
3131 /// It should be equal to the primal value scaled by \ref dualScale
3134 /// \pre Either run() or start() must be called before using this function.
3135 Value dualValue() const {
3137 for (NodeIt n(_graph); n != INVALID; ++n) {
3138 sum += nodeValue(n);
3140 for (int i = 0; i < blossomNum(); ++i) {
3141 sum += blossomValue(i) * (blossomSize(i) / 2);
3146 /// \brief Return the dual value (potential) of the given node.
3148 /// This function returns the dual value (potential) of the given node.
3150 /// \pre Either run() or start() must be called before using this function.
3151 Value nodeValue(const Node& n) const {
3152 return (*_node_potential)[n];
3155 /// \brief Return the number of the blossoms in the basis.
3157 /// This function returns the number of the blossoms in the basis.
3159 /// \pre Either run() or start() must be called before using this function.
3161 int blossomNum() const {
3162 return _blossom_potential.size();
3165 /// \brief Return the number of the nodes in the given blossom.
3167 /// This function returns the number of the nodes in the given blossom.
3169 /// \pre Either run() or start() must be called before using this function.
3171 int blossomSize(int k) const {
3172 return _blossom_potential[k].end - _blossom_potential[k].begin;
3175 /// \brief Return the dual value (ptential) of the given blossom.
3177 /// This function returns the dual value (ptential) of the given blossom.
3179 /// \pre Either run() or start() must be called before using this function.
3180 Value blossomValue(int k) const {
3181 return _blossom_potential[k].value;
3184 /// \brief Iterator for obtaining the nodes of a blossom.
3186 /// This class provides an iterator for obtaining the nodes of the
3187 /// given blossom. It lists a subset of the nodes.
3188 /// Before using this iterator, you must allocate a
3189 /// MaxWeightedPerfectMatching class and execute it.
3193 /// \brief Constructor.
3195 /// Constructor to get the nodes of the given variable.
3197 /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
3198 /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
3199 /// must be called before initializing this iterator.
3200 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
3201 : _algorithm(&algorithm)
3203 _index = _algorithm->_blossom_potential[variable].begin;
3204 _last = _algorithm->_blossom_potential[variable].end;
3207 /// \brief Conversion to \c Node.
3209 /// Conversion to \c Node.
3210 operator Node() const {
3211 return _algorithm->_blossom_node_list[_index];
3214 /// \brief Increment operator.
3216 /// Increment operator.
3217 BlossomIt& operator++() {
3222 /// \brief Validity checking
3224 /// This function checks whether the iterator is invalid.
3225 bool operator==(Invalid) const { return _index == _last; }
3227 /// \brief Validity checking
3229 /// This function checks whether the iterator is valid.
3230 bool operator!=(Invalid) const { return _index != _last; }
3233 const MaxWeightedPerfectMatching* _algorithm;
3242 } //END OF NAMESPACE LEMON
3244 #endif //LEMON_MAX_MATCHING_H