Improvements in CycleCanceling.
Main changes:
- Use function parameter instead of #define commands to select negative
cycle detection method.
- Change the name of private members to start with "_".
- Change the name of function parameters not to start with "_".
- Remove unnecessary documentation for private members.
- Doc improvements.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
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_DYNAMIC_TREE_H
20 #define LEMON_DYNAMIC_TREE_H
24 /// \brief The dynamic tree data structure of Sleator and Tarjan.
29 #include <lemon/tolerance.h>
35 /// \brief The dynamic tree data structure of Sleator and Tarjan.
37 /// This class provides an implementation of the dynamic tree data
38 /// structure for maintaining a set of node-disjoint rooted
39 /// trees. Each item has an associated value, and the item with
40 /// minimum value can be find in \f$O(\log(n)\f$ on the path from a
41 /// node to the its root, and the items on such path can be
42 /// increased or decreased globally with a certain value in the same
43 /// running time. We regard a tree edge as directed toward the root,
44 /// that is from child to parent. Its structure can be modified by
45 /// two basic operations: \e link(v,w) adds an edge between a root v
46 /// and a node w in a different component; \e cut(v) removes the
47 /// edge between v and its parent.
49 /// \param _Value The value type of the items.
50 /// \param _ItemIntMap Converts item type of node to integer.
51 /// \param _Tolerance The tolerance class to handle computation
53 /// \param _enableSize If true then the data structre manatain the
54 /// size of each tree. The feature is used in \ref GoldbergTarjan
55 /// algorithm. The default value is true.
57 /// \author Hamori Tamas
59 template <typename _Value, typename _ItemIntMap,
60 typename _Tolerance, bool _enableSize>
62 template <typename _Value, typename _ItemIntMap,
63 typename _Tolerance = lemon::Tolerance<_Value>,
64 bool _enableSize = true>
68 /// \brief The integer map on the items.
69 typedef _ItemIntMap ItemIntMap;
70 /// \brief The item type of nodes.
71 typedef typename ItemIntMap::Key Item;
72 /// \brief The value type of the algorithms.
74 /// \brief The tolerance used by the algorithm.
75 typedef _Tolerance Tolerance;
81 std::vector<ItemData> _data;
87 /// \brief The constructor of the class.
89 /// \param iim The integer map on the items.
90 /// \param tolerance Tolerance class.
91 DynamicTree(ItemIntMap &iim, const Tolerance& tolerance = Tolerance())
92 : _iim(iim), _max_value(std::numeric_limits<Value>::max()),
93 _tolerance(tolerance) {}
97 /// \brief Clears the data structure
99 /// Clears the data structure
104 /// \brief Sets the tolerance used by algorithm.
106 /// Sets the tolerance used by algorithm.
107 void tolerance(const Tolerance& tolerance) const {
108 _tolerance = tolerance;
112 /// \brief Returns the tolerance used by algorithm.
114 /// Returns the tolerance used by algorithm.
115 const Tolerance& tolerance() const {
119 /// \brief Create a new tree containing a single node with cost zero.
120 void makeTree(const Item &item) {
121 _data[makePath(item)].successor = -1;
124 /// \brief Return the root of the tree containing node with itemtype
126 Item findRoot(const Item &item) {
127 return _data[findTail(expose(_iim[item]))].id;
130 /// \brief Return the the value of nodes in the tree containing
131 /// node with itemtype \e item.
132 int findSize(const Item &item) {
133 return _data[expose(_iim[item])].size;
136 /// \brief Return the minimum cost containing node.
138 /// Return into \e d the minimum cost on the tree path from \e item
139 /// to findRoot(item). Return the last item (closest to its root)
140 /// on this path of the minimum cost.
141 Item findCost(const Item &item, Value& d){
142 return _data[findPathCost(expose(_iim[item]),d)].id;
145 /// \brief Add \e x value to the cost of every node on the path from
146 /// \e item to findRoot(item).
147 void addCost(const Item &item, Value x) {
148 addPathCost(expose(_iim[item]), x);
151 /// \brief Combine the trees containing nodes \e item1 and \e item2
152 /// by adding an edge from \e item1 \e item2.
154 /// This operation assumes that \e item1 is root and \e item2 is in
155 /// a different tree.
156 void link(const Item &item1, const Item &item2){
160 join(-1, expose(v), p);
161 _data[v].successor = -1;
162 _data[v].size += _data[p].size;
166 /// \brief Divide the tree containing node \e item into two trees by
167 /// deleting the edge out of \e item.
169 /// This operation assumes that \e item is not a tree root.
170 void cut(const Item &item) {
176 _data[p].successor = v;
178 _data[v].size -= _data[q].size;
180 _data[q].successor = _data[v].successor;
182 _data[v].successor = -1;
186 Item parent(const Item &item){
187 return _data[_iim[item].p].id;
190 ///\brief Return the upper bound of the costs.
191 Value maxValue() const {
197 int makePath(const Item &item) {
198 _iim.set(item, _data.size());
204 int findPath(int v) {
209 int findPathCost(int p, Value &d) {
210 while ((_data[p].right != -1 &&
211 !_tolerance.less(0, _data[_data[p].right].dmin)) ||
212 (_data[p].left != -1 && _tolerance.less(0, _data[p].dcost))) {
213 if (_data[p].right != -1 &&
214 !_tolerance.less(0, _data[_data[p].right].dmin)) {
216 } else if (_data[p].left != -1 &&
217 !_tolerance.less(0, _data[_data[p].left].dmin)) {
227 while (_data[p].right != -1) {
234 void addPathCost(int p, Value x) {
235 if (!_tolerance.less(x, _max_value)) {
238 } else if (!_tolerance.less(-x, _max_value)) {
246 void join(int p, int v, int q) {
247 Value min = _max_value;
248 Value pmin = _max_value;
249 Value vmin = _data[v].dmin;
250 Value qmin = _max_value;
252 pmin = _data[p].dmin;
255 qmin = _data[q].dmin;
258 if (_tolerance.less(vmin, qmin)) {
259 if (_tolerance.less(vmin,pmin)) {
264 } else if (_tolerance.less(qmin,pmin)) {
272 _data[p].dmin -= min;
276 if (_tolerance.less(_data[q].dmin,_max_value)) {
277 _data[q].dmin -= min;
282 if (_tolerance.less(min,_max_value)) {
283 _data[v].dcost = _data[v].dmin - min;
288 void split(int &p, int v, int &q){
291 if (_data[v].left != -1){
293 _data[p].dmin += _data[v].dmin;
294 _data[p].parent = -1;
298 if (_data[v].right != -1) {
300 if (_tolerance.less(_data[q].dmin, _max_value)) {
301 _data[q].dmin += _data[v].dmin;
303 _data[q].parent = -1;
306 if (_tolerance.less(_data[v].dcost, _max_value)) {
307 _data[v].dmin += _data[v].dcost;
310 _data[v].dmin = _data[v].dcost;
318 w = _data[findPath(v)].successor;
321 _data[q].successor = v;
327 _data[p].successor = -1;
332 while (_data[v].parent != -1) {
333 if (v == _data[_data[v].parent].left) {
334 if (_data[_data[v].parent].parent == -1) {
337 if (_data[v].parent == _data[_data[_data[v].parent].parent].left) {
338 zig(_data[v].parent);
346 if (_data[_data[v].parent].parent == -1) {
349 if (_data[v].parent == _data[_data[_data[v].parent].parent].left) {
353 zag(_data[v].parent);
363 Value min = _data[_data[v].parent].dmin;
364 int a = _data[v].parent;
366 Value aa = _data[a].dcost;
367 if (_tolerance.less(aa, _max_value)) {
373 Value ab = min + _data[b].dmin;
374 Value bb = _data[b].dcost;
375 if (_tolerance.less(bb, _max_value)) {
380 Value cc = _max_value;
381 if (_data[a].right != -1) {
384 if (_tolerance.less(cc, _max_value)) {
390 Value dd = _max_value;
391 if (_data[v].left != -1){
393 dd = ab + _data[d].dmin;
397 Value ee = _max_value;
398 if (_data[v].right != -1) {
400 ee = ab + _data[e].dmin;
404 if (_tolerance.less(0, _data[b].dmin) ||
405 (e != -1 && !_tolerance.less(0, _data[e].dmin))) {
408 if (_tolerance.less(aa, cc)) {
409 if (_tolerance.less(aa, ee)) {
414 } else if (_tolerance.less(cc, ee)) {
422 if (_tolerance.less(aa, _max_value)) {
423 _data[a].dcost -= min2;
425 _data[a].dmin = min2;
426 if (_tolerance.less(min2,_max_value)) {
427 _data[a].dmin -= min;
429 _data[a].size -= _data[b].size;
431 if (_tolerance.less(bb, _max_value)) {
432 _data[b].dcost -= min;
435 _data[b].size += _data[a].size;
438 if (_tolerance.less(cc, _max_value)) {
439 _data[c].dmin -= min2;
443 _data[d].dmin = dd - min;
444 _data[a].size += _data[d].size;
445 _data[b].size -= _data[d].size;
448 _data[e].dmin = ee - min2;
451 int w = _data[v].parent;
452 _data[v].successor = _data[w].successor;
453 _data[w].successor = -1;
454 _data[v].parent = _data[w].parent;
456 _data[w].left = _data[v].right;
458 if (_data[v].parent != -1){
459 if (_data[_data[v].parent].right == w) {
460 _data[_data[v].parent].right = v;
462 _data[_data[v].parent].left = v;
465 if (_data[w].left != -1){
466 _data[_data[w].left].parent = w;
473 Value min = _data[_data[v].parent].dmin;
475 int a = _data[v].parent;
476 Value aa = _data[a].dcost;
477 if (_tolerance.less(aa, _max_value)) {
482 Value ab = min + _data[b].dmin;
483 Value bb = _data[b].dcost;
484 if (_tolerance.less(bb, _max_value)) {
489 Value cc = _max_value;
490 if (_data[a].left != -1){
492 cc = min + _data[c].dmin;
496 Value dd = _max_value;
497 if (_data[v].right!=-1) {
500 if (_tolerance.less(dd, _max_value)) {
506 Value ee = _max_value;
507 if (_data[v].left != -1){
509 ee = ab + _data[e].dmin;
513 if (_tolerance.less(0, _data[b].dmin) ||
514 (e != -1 && !_tolerance.less(0, _data[e].dmin))) {
517 if (_tolerance.less(aa, cc)) {
518 if (_tolerance.less(aa, ee)) {
523 } else if (_tolerance.less(cc, ee)) {
530 if (_tolerance.less(aa, _max_value)) {
531 _data[a].dcost -= min2;
533 _data[a].dmin = min2;
534 if (_tolerance.less(min2, _max_value)) {
535 _data[a].dmin -= min;
537 _data[a].size -= _data[b].size;
539 if (_tolerance.less(bb, _max_value)) {
540 _data[b].dcost -= min;
543 _data[b].size += _data[a].size;
545 _data[c].dmin = cc - min2;
549 _data[a].size += _data[d].size;
550 _data[b].size -= _data[d].size;
551 if (_tolerance.less(dd, _max_value)) {
552 _data[d].dmin -= min;
556 _data[e].dmin = ee - min2;
559 int w = _data[v].parent;
560 _data[v].successor = _data[w].successor;
561 _data[w].successor = -1;
562 _data[v].parent = _data[w].parent;
564 _data[w].right = _data[v].left;
566 if (_data[v].parent != -1){
567 if (_data[_data[v].parent].left == w) {
568 _data[_data[v].parent].left = v;
570 _data[_data[v].parent].right = v;
573 if (_data[w].right != -1){
574 _data[_data[w].right].parent = w;
592 ItemData(const Item &item)
593 : id(item), size(1), successor(), parent(-1),
594 left(-1), right(-1), dmin(0), dcost(0) {}
599 template <typename _Value, typename _ItemIntMap, typename _Tolerance>
600 class DynamicTree<_Value, _ItemIntMap, _Tolerance, false> {
602 typedef _ItemIntMap ItemIntMap;
603 typedef typename ItemIntMap::Key Item;
604 typedef _Value Value;
605 typedef _Tolerance Tolerance;
611 std::vector<ItemData> _data;
614 Tolerance _tolerance;
617 DynamicTree(ItemIntMap &iim, const Tolerance& tolerance = Tolerance())
618 : _iim(iim), _max_value(std::numeric_limits<Value>::max()),
619 _tolerance(tolerance) {}
627 void tolerance(const Tolerance& tolerance) const {
628 _tolerance = tolerance;
632 const Tolerance& tolerance() const {
636 void makeTree(const Item &item) {
637 _data[makePath(item)].successor = -1;
640 Item findRoot(const Item &item) {
641 return _data[findTail(expose(_iim[item]))].id;
644 Item findCost(const Item &item, Value& d){
645 return _data[findPathCost(expose(_iim[item]),d)].id;
648 void addCost(const Item &item, Value x){
649 addPathCost(expose(_iim[item]), x);
652 void link(const Item &item1, const Item &item2){
656 join(-1, expose(v), p);
657 _data[v].successor = -1;
660 void cut(const Item &item) {
666 _data[p].successor = v;
669 _data[q].successor = _data[v].successor;
671 _data[v].successor = -1;
674 Item parent(const Item &item){
675 return _data[_iim[item].p].id;
678 Value maxValue() const {
684 int makePath(const Item &item) {
685 _iim.set(item, _data.size());
691 int findPath(int v) {
696 int findPathCost(int p, Value &d) {
697 while ((_data[p].right != -1 &&
698 !_tolerance.less(0, _data[_data[p].right].dmin)) ||
699 (_data[p].left != -1 && _tolerance.less(0, _data[p].dcost))) {
700 if (_data[p].right != -1 &&
701 !_tolerance.less(0, _data[_data[p].right].dmin)) {
703 } else if (_data[p].left != -1 &&
704 !_tolerance.less(0, _data[_data[p].left].dmin)){
713 int findTail(int p) {
714 while (_data[p].right != -1) {
721 void addPathCost(int p, Value x) {
722 if (!_tolerance.less(x, _max_value)) {
723 _data[p].dmin = x;_data[p].dcost = x;
724 } else if (!_tolerance.less(-x, _max_value)) {
732 void join(int p, int v, int q) {
733 Value min = _max_value;
734 Value pmin = _max_value;
735 Value vmin = _data[v].dmin;
736 Value qmin = _max_value;
738 pmin = _data[p].dmin;
741 qmin = _data[q].dmin;
744 if (_tolerance.less(vmin, qmin)) {
745 if (_tolerance.less(vmin,pmin)) {
750 } else if (_tolerance.less(qmin,pmin)) {
758 _data[p].dmin -= min;
762 if (_tolerance.less(_data[q].dmin,_max_value)) {
763 _data[q].dmin -= min;
768 if (_tolerance.less(min, _max_value)) {
769 _data[v].dcost = _data[v].dmin - min;
774 void split(int &p, int v, int &q){
777 if (_data[v].left != -1){
779 _data[p].dmin += _data[v].dmin;
780 _data[p].parent = -1;
784 if (_data[v].right != -1) {
786 if (_tolerance.less(_data[q].dmin, _max_value)) {
787 _data[q].dmin += _data[v].dmin;
789 _data[q].parent = -1;
792 if (_tolerance.less(_data[v].dcost, _max_value)) {
793 _data[v].dmin += _data[v].dcost;
796 _data[v].dmin = _data[v].dcost;
804 w = _data[findPath(v)].successor;
807 _data[q].successor = v;
813 _data[p].successor = -1;
818 while (_data[v].parent != -1) {
819 if (v == _data[_data[v].parent].left) {
820 if (_data[_data[v].parent].parent == -1) {
823 if (_data[v].parent == _data[_data[_data[v].parent].parent].left) {
824 zig(_data[v].parent);
832 if (_data[_data[v].parent].parent == -1) {
835 if (_data[v].parent == _data[_data[_data[v].parent].parent].left) {
839 zag(_data[v].parent);
849 Value min = _data[_data[v].parent].dmin;
850 int a = _data[v].parent;
852 Value aa = _data[a].dcost;
853 if (_tolerance.less(aa, _max_value)) {
859 Value ab = min + _data[b].dmin;
860 Value bb = _data[b].dcost;
861 if (_tolerance.less(bb, _max_value)) {
866 Value cc = _max_value;
867 if (_data[a].right != -1) {
870 if (_tolerance.less(cc, _max_value)) {
876 Value dd = _max_value;
877 if (_data[v].left != -1){
879 dd = ab + _data[d].dmin;
883 Value ee = _max_value;
884 if (_data[v].right != -1) {
886 ee = ab + _data[e].dmin;
890 if (_tolerance.less(0, _data[b].dmin) ||
891 (e != -1 && !_tolerance.less(0, _data[e].dmin))) {
894 if (_tolerance.less(aa, cc)) {
895 if (_tolerance.less(aa, ee)) {
900 } else if (_tolerance.less(cc, ee)) {
908 if (_tolerance.less(aa, _max_value)) {
909 _data[a].dcost -= min2;
911 _data[a].dmin = min2;
912 if (_tolerance.less(min2,_max_value)) {
913 _data[a].dmin -= min;
916 if (_tolerance.less(bb, _max_value)) {
917 _data[b].dcost -= min;
922 if (_tolerance.less(cc, _max_value)) {
923 _data[c].dmin -= min2;
927 _data[d].dmin = dd - min;
930 _data[e].dmin = ee - min2;
933 int w = _data[v].parent;
934 _data[v].successor = _data[w].successor;
935 _data[w].successor = -1;
936 _data[v].parent = _data[w].parent;
938 _data[w].left = _data[v].right;
940 if (_data[v].parent != -1){
941 if (_data[_data[v].parent].right == w) {
942 _data[_data[v].parent].right = v;
944 _data[_data[v].parent].left = v;
947 if (_data[w].left != -1){
948 _data[_data[w].left].parent = w;
955 Value min = _data[_data[v].parent].dmin;
957 int a = _data[v].parent;
958 Value aa = _data[a].dcost;
959 if (_tolerance.less(aa, _max_value)) {
964 Value ab = min + _data[b].dmin;
965 Value bb = _data[b].dcost;
966 if (_tolerance.less(bb, _max_value)) {
971 Value cc = _max_value;
972 if (_data[a].left != -1){
974 cc = min + _data[c].dmin;
978 Value dd = _max_value;
979 if (_data[v].right!=-1) {
982 if (_tolerance.less(dd, _max_value)) {
988 Value ee = _max_value;
989 if (_data[v].left != -1){
991 ee = ab + _data[e].dmin;
995 if (_tolerance.less(0, _data[b].dmin) ||
996 (e != -1 && !_tolerance.less(0, _data[e].dmin))) {
999 if (_tolerance.less(aa, cc)) {
1000 if (_tolerance.less(aa, ee)) {
1005 } else if (_tolerance.less(cc, ee)) {
1011 _data[a].dcost = aa;
1012 if (_tolerance.less(aa, _max_value)) {
1013 _data[a].dcost -= min2;
1015 _data[a].dmin = min2;
1016 if (_tolerance.less(min2, _max_value)) {
1017 _data[a].dmin -= min;
1019 _data[b].dcost = bb;
1020 if (_tolerance.less(bb, _max_value)) {
1021 _data[b].dcost -= min;
1023 _data[b].dmin = min;
1025 _data[c].dmin = cc - min2;
1029 if (_tolerance.less(dd, _max_value)) {
1030 _data[d].dmin -= min;
1034 _data[e].dmin = ee - min2;
1037 int w = _data[v].parent;
1038 _data[v].successor = _data[w].successor;
1039 _data[w].successor = -1;
1040 _data[v].parent = _data[w].parent;
1041 _data[w].parent = v;
1042 _data[w].right = _data[v].left;
1044 if (_data[v].parent != -1){
1045 if (_data[_data[v].parent].left == w) {
1046 _data[_data[v].parent].left = v;
1048 _data[_data[v].parent].right = v;
1051 if (_data[w].right != -1){
1052 _data[_data[w].right].parent = w;
1069 ItemData(const Item &item)
1070 : id(item), successor(), parent(-1),
1071 left(-1), right(-1), dmin(0), dcost(0) {}