3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
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
18 #ifndef LEMON_DYNAMIC_TREE_H
19 #define LEMON_DYNAMIC_TREE_H
23 /// \brief The dynamic tree data structure of Sleator and Tarjan.
28 #include <lemon/tolerance.h>
34 /// \brief The dynamic tree data structure of Sleator and Tarjan.
36 /// This class provides an implementation of the dynamic tree data
37 /// structure for maintaining a set of node-disjoint rooted
38 /// trees. Each item has an associated value, and the item with
39 /// minimum value can be find in \f$O(\log(n)\f$ on the path from a
40 /// node to the its root, and the items on such path can be
41 /// increased or decreased globally with a certain value in the same
42 /// running time. We regard a tree edge as directed toward the root,
43 /// that is from child to parent. Its structure can be modified by
44 /// two basic operations: \e link(v,w) adds an edge between a root v
45 /// and a node w in a different component; \e cut(v) removes the
46 /// edge between v and its parent.
48 /// \param _Value The value type of the items.
49 /// \param _ItemIntMap Converts item type of node to integer.
50 /// \param _Tolerance The tolerance class to handle computation
52 /// \param _enableSize If true then the data structre manatain the
53 /// size of each tree. The feature is used in \ref GoldbergTarjan
54 /// algorithm. The default value is true.
56 /// \author Hamori Tamas
58 template <typename _Value, typename _ItemIntMap,
59 typename _Tolerance, bool _enableSize>
61 template <typename _Value, typename _ItemIntMap,
62 typename _Tolerance = lemon::Tolerance<_Value>,
63 bool _enableSize = true>
67 /// \brief The integer map on the items.
68 typedef _ItemIntMap ItemIntMap;
69 /// \brief The item type of nodes.
70 typedef typename ItemIntMap::Key Item;
71 /// \brief The value type of the algorithms.
73 /// \brief The tolerance used by the algorithm.
74 typedef _Tolerance Tolerance;
80 std::vector<ItemData> _data;
86 /// \brief The constructor of the class.
88 /// \param iim The integer map on the items.
89 /// \param tolerance Tolerance class.
90 DynamicTree(ItemIntMap &iim, const Tolerance& tolerance = Tolerance())
91 : _iim(iim), _max_value(std::numeric_limits<Value>::max()),
92 _tolerance(tolerance) {}
96 /// \brief Clears the data structure
98 /// Clears the data structure
103 /// \brief Sets the tolerance used by algorithm.
105 /// Sets the tolerance used by algorithm.
106 void tolerance(const Tolerance& tolerance) const {
107 _tolerance = tolerance;
111 /// \brief Returns the tolerance used by algorithm.
113 /// Returns the tolerance used by algorithm.
114 const Tolerance& tolerance() const {
118 /// \brief Create a new tree containing a single node with cost zero.
119 void makeTree(const Item &item) {
120 _data[makePath(item)].successor = -1;
123 /// \brief Return the root of the tree containing node with itemtype
125 Item findRoot(const Item &item) {
126 return _data[findTail(expose(_iim[item]))].id;
129 /// \brief Return the the value of nodes in the tree containing
130 /// node with itemtype \e item.
131 int findSize(const Item &item) {
132 return _data[expose(_iim[item])].size;
135 /// \brief Return the minimum cost containing node.
137 /// Return into \e d the minimum cost on the tree path from \e item
138 /// to findRoot(item). Return the last item (closest to its root)
139 /// on this path of the minimum cost.
140 Item findCost(const Item &item, Value& d){
141 return _data[findPathCost(expose(_iim[item]),d)].id;
144 /// \brief Add \e x value to the cost of every node on the path from
145 /// \e item to findRoot(item).
146 void addCost(const Item &item, Value x) {
147 addPathCost(expose(_iim[item]), x);
150 /// \brief Combine the trees containing nodes \e item1 and \e item2
151 /// by adding an edge from \e item1 \e item2.
153 /// This operation assumes that \e item1 is root and \e item2 is in
154 /// a different tree.
155 void link(const Item &item1, const Item &item2){
159 join(-1, expose(v), p);
160 _data[v].successor = -1;
161 _data[v].size += _data[p].size;
165 /// \brief Divide the tree containing node \e item into two trees by
166 /// deleting the edge out of \e item.
168 /// This operation assumes that \e item is not a tree root.
169 void cut(const Item &item) {
175 _data[p].successor = v;
177 _data[v].size -= _data[q].size;
179 _data[q].successor = _data[v].successor;
181 _data[v].successor = -1;
185 Item parent(const Item &item){
186 return _data[_iim[item].p].id;
189 ///\brief Return the upper bound of the costs.
190 Value maxValue() const {
196 int makePath(const Item &item) {
197 _iim.set(item, _data.size());
203 int findPath(int v) {
208 int findPathCost(int p, Value &d) {
209 while ((_data[p].right != -1 &&
210 !_tolerance.less(0, _data[_data[p].right].dmin)) ||
211 (_data[p].left != -1 && _tolerance.less(0, _data[p].dcost))) {
212 if (_data[p].right != -1 &&
213 !_tolerance.less(0, _data[_data[p].right].dmin)) {
215 } else if (_data[p].left != -1 &&
216 !_tolerance.less(0, _data[_data[p].left].dmin)) {
226 while (_data[p].right != -1) {
233 void addPathCost(int p, Value x) {
234 if (!_tolerance.less(x, _max_value)) {
237 } else if (!_tolerance.less(-x, _max_value)) {
245 void join(int p, int v, int q) {
246 Value min = _max_value;
247 Value pmin = _max_value;
248 Value vmin = _data[v].dmin;
249 Value qmin = _max_value;
251 pmin = _data[p].dmin;
254 qmin = _data[q].dmin;
257 if (_tolerance.less(vmin, qmin)) {
258 if (_tolerance.less(vmin,pmin)) {
263 } else if (_tolerance.less(qmin,pmin)) {
271 _data[p].dmin -= min;
275 if (_tolerance.less(_data[q].dmin,_max_value)) {
276 _data[q].dmin -= min;
281 if (_tolerance.less(min,_max_value)) {
282 _data[v].dcost = _data[v].dmin - min;
287 void split(int &p, int v, int &q){
290 if (_data[v].left != -1){
292 _data[p].dmin += _data[v].dmin;
293 _data[p].parent = -1;
297 if (_data[v].right != -1) {
299 if (_tolerance.less(_data[q].dmin, _max_value)) {
300 _data[q].dmin += _data[v].dmin;
302 _data[q].parent = -1;
305 if (_tolerance.less(_data[v].dcost, _max_value)) {
306 _data[v].dmin += _data[v].dcost;
309 _data[v].dmin = _data[v].dcost;
317 w = _data[findPath(v)].successor;
320 _data[q].successor = v;
326 _data[p].successor = -1;
331 while (_data[v].parent != -1) {
332 if (v == _data[_data[v].parent].left) {
333 if (_data[_data[v].parent].parent == -1) {
336 if (_data[v].parent == _data[_data[_data[v].parent].parent].left) {
337 zig(_data[v].parent);
345 if (_data[_data[v].parent].parent == -1) {
348 if (_data[v].parent == _data[_data[_data[v].parent].parent].left) {
352 zag(_data[v].parent);
362 Value min = _data[_data[v].parent].dmin;
363 int a = _data[v].parent;
365 Value aa = _data[a].dcost;
366 if (_tolerance.less(aa, _max_value)) {
372 Value ab = min + _data[b].dmin;
373 Value bb = _data[b].dcost;
374 if (_tolerance.less(bb, _max_value)) {
379 Value cc = _max_value;
380 if (_data[a].right != -1) {
383 if (_tolerance.less(cc, _max_value)) {
389 Value dd = _max_value;
390 if (_data[v].left != -1){
392 dd = ab + _data[d].dmin;
396 Value ee = _max_value;
397 if (_data[v].right != -1) {
399 ee = ab + _data[e].dmin;
403 if (_tolerance.less(0, _data[b].dmin) ||
404 (e != -1 && !_tolerance.less(0, _data[e].dmin))) {
407 if (_tolerance.less(aa, cc)) {
408 if (_tolerance.less(aa, ee)) {
413 } else if (_tolerance.less(cc, ee)) {
421 if (_tolerance.less(aa, _max_value)) {
422 _data[a].dcost -= min2;
424 _data[a].dmin = min2;
425 if (_tolerance.less(min2,_max_value)) {
426 _data[a].dmin -= min;
428 _data[a].size -= _data[b].size;
430 if (_tolerance.less(bb, _max_value)) {
431 _data[b].dcost -= min;
434 _data[b].size += _data[a].size;
437 if (_tolerance.less(cc, _max_value)) {
438 _data[c].dmin -= min2;
442 _data[d].dmin = dd - min;
443 _data[a].size += _data[d].size;
444 _data[b].size -= _data[d].size;
447 _data[e].dmin = ee - min2;
450 int w = _data[v].parent;
451 _data[v].successor = _data[w].successor;
452 _data[w].successor = -1;
453 _data[v].parent = _data[w].parent;
455 _data[w].left = _data[v].right;
457 if (_data[v].parent != -1){
458 if (_data[_data[v].parent].right == w) {
459 _data[_data[v].parent].right = v;
461 _data[_data[v].parent].left = v;
464 if (_data[w].left != -1){
465 _data[_data[w].left].parent = w;
472 Value min = _data[_data[v].parent].dmin;
474 int a = _data[v].parent;
475 Value aa = _data[a].dcost;
476 if (_tolerance.less(aa, _max_value)) {
481 Value ab = min + _data[b].dmin;
482 Value bb = _data[b].dcost;
483 if (_tolerance.less(bb, _max_value)) {
488 Value cc = _max_value;
489 if (_data[a].left != -1){
491 cc = min + _data[c].dmin;
495 Value dd = _max_value;
496 if (_data[v].right!=-1) {
499 if (_tolerance.less(dd, _max_value)) {
505 Value ee = _max_value;
506 if (_data[v].left != -1){
508 ee = ab + _data[e].dmin;
512 if (_tolerance.less(0, _data[b].dmin) ||
513 (e != -1 && !_tolerance.less(0, _data[e].dmin))) {
516 if (_tolerance.less(aa, cc)) {
517 if (_tolerance.less(aa, ee)) {
522 } else if (_tolerance.less(cc, ee)) {
529 if (_tolerance.less(aa, _max_value)) {
530 _data[a].dcost -= min2;
532 _data[a].dmin = min2;
533 if (_tolerance.less(min2, _max_value)) {
534 _data[a].dmin -= min;
536 _data[a].size -= _data[b].size;
538 if (_tolerance.less(bb, _max_value)) {
539 _data[b].dcost -= min;
542 _data[b].size += _data[a].size;
544 _data[c].dmin = cc - min2;
548 _data[a].size += _data[d].size;
549 _data[b].size -= _data[d].size;
550 if (_tolerance.less(dd, _max_value)) {
551 _data[d].dmin -= min;
555 _data[e].dmin = ee - min2;
558 int w = _data[v].parent;
559 _data[v].successor = _data[w].successor;
560 _data[w].successor = -1;
561 _data[v].parent = _data[w].parent;
563 _data[w].right = _data[v].left;
565 if (_data[v].parent != -1){
566 if (_data[_data[v].parent].left == w) {
567 _data[_data[v].parent].left = v;
569 _data[_data[v].parent].right = v;
572 if (_data[w].right != -1){
573 _data[_data[w].right].parent = w;
591 ItemData(const Item &item)
592 : id(item), size(1), successor(), parent(-1),
593 left(-1), right(-1), dmin(0), dcost(0) {}
598 template <typename _Value, typename _ItemIntMap, typename _Tolerance>
599 class DynamicTree<_Value, _ItemIntMap, _Tolerance, false> {
601 typedef _ItemIntMap ItemIntMap;
602 typedef typename ItemIntMap::Key Item;
603 typedef _Value Value;
604 typedef _Tolerance Tolerance;
610 std::vector<ItemData> _data;
613 Tolerance _tolerance;
616 DynamicTree(ItemIntMap &iim, const Tolerance& tolerance = Tolerance())
617 : _iim(iim), _max_value(std::numeric_limits<Value>::max()),
618 _tolerance(tolerance) {}
626 void tolerance(const Tolerance& tolerance) const {
627 _tolerance = tolerance;
631 const Tolerance& tolerance() const {
635 void makeTree(const Item &item) {
636 _data[makePath(item)].successor = -1;
639 Item findRoot(const Item &item) {
640 return _data[findTail(expose(_iim[item]))].id;
643 Item findCost(const Item &item, Value& d){
644 return _data[findPathCost(expose(_iim[item]),d)].id;
647 void addCost(const Item &item, Value x){
648 addPathCost(expose(_iim[item]), x);
651 void link(const Item &item1, const Item &item2){
655 join(-1, expose(v), p);
656 _data[v].successor = -1;
659 void cut(const Item &item) {
665 _data[p].successor = v;
668 _data[q].successor = _data[v].successor;
670 _data[v].successor = -1;
673 Item parent(const Item &item){
674 return _data[_iim[item].p].id;
677 Value maxValue() const {
683 int makePath(const Item &item) {
684 _iim.set(item, _data.size());
690 int findPath(int v) {
695 int findPathCost(int p, Value &d) {
696 while ((_data[p].right != -1 &&
697 !_tolerance.less(0, _data[_data[p].right].dmin)) ||
698 (_data[p].left != -1 && _tolerance.less(0, _data[p].dcost))) {
699 if (_data[p].right != -1 &&
700 !_tolerance.less(0, _data[_data[p].right].dmin)) {
702 } else if (_data[p].left != -1 &&
703 !_tolerance.less(0, _data[_data[p].left].dmin)){
712 int findTail(int p) {
713 while (_data[p].right != -1) {
720 void addPathCost(int p, Value x) {
721 if (!_tolerance.less(x, _max_value)) {
722 _data[p].dmin = x;_data[p].dcost = x;
723 } else if (!_tolerance.less(-x, _max_value)) {
731 void join(int p, int v, int q) {
732 Value min = _max_value;
733 Value pmin = _max_value;
734 Value vmin = _data[v].dmin;
735 Value qmin = _max_value;
737 pmin = _data[p].dmin;
740 qmin = _data[q].dmin;
743 if (_tolerance.less(vmin, qmin)) {
744 if (_tolerance.less(vmin,pmin)) {
749 } else if (_tolerance.less(qmin,pmin)) {
757 _data[p].dmin -= min;
761 if (_tolerance.less(_data[q].dmin,_max_value)) {
762 _data[q].dmin -= min;
767 if (_tolerance.less(min, _max_value)) {
768 _data[v].dcost = _data[v].dmin - min;
773 void split(int &p, int v, int &q){
776 if (_data[v].left != -1){
778 _data[p].dmin += _data[v].dmin;
779 _data[p].parent = -1;
783 if (_data[v].right != -1) {
785 if (_tolerance.less(_data[q].dmin, _max_value)) {
786 _data[q].dmin += _data[v].dmin;
788 _data[q].parent = -1;
791 if (_tolerance.less(_data[v].dcost, _max_value)) {
792 _data[v].dmin += _data[v].dcost;
795 _data[v].dmin = _data[v].dcost;
803 w = _data[findPath(v)].successor;
806 _data[q].successor = v;
812 _data[p].successor = -1;
817 while (_data[v].parent != -1) {
818 if (v == _data[_data[v].parent].left) {
819 if (_data[_data[v].parent].parent == -1) {
822 if (_data[v].parent == _data[_data[_data[v].parent].parent].left) {
823 zig(_data[v].parent);
831 if (_data[_data[v].parent].parent == -1) {
834 if (_data[v].parent == _data[_data[_data[v].parent].parent].left) {
838 zag(_data[v].parent);
848 Value min = _data[_data[v].parent].dmin;
849 int a = _data[v].parent;
851 Value aa = _data[a].dcost;
852 if (_tolerance.less(aa, _max_value)) {
858 Value ab = min + _data[b].dmin;
859 Value bb = _data[b].dcost;
860 if (_tolerance.less(bb, _max_value)) {
865 Value cc = _max_value;
866 if (_data[a].right != -1) {
869 if (_tolerance.less(cc, _max_value)) {
875 Value dd = _max_value;
876 if (_data[v].left != -1){
878 dd = ab + _data[d].dmin;
882 Value ee = _max_value;
883 if (_data[v].right != -1) {
885 ee = ab + _data[e].dmin;
889 if (_tolerance.less(0, _data[b].dmin) ||
890 (e != -1 && !_tolerance.less(0, _data[e].dmin))) {
893 if (_tolerance.less(aa, cc)) {
894 if (_tolerance.less(aa, ee)) {
899 } else if (_tolerance.less(cc, ee)) {
907 if (_tolerance.less(aa, _max_value)) {
908 _data[a].dcost -= min2;
910 _data[a].dmin = min2;
911 if (_tolerance.less(min2,_max_value)) {
912 _data[a].dmin -= min;
915 if (_tolerance.less(bb, _max_value)) {
916 _data[b].dcost -= min;
921 if (_tolerance.less(cc, _max_value)) {
922 _data[c].dmin -= min2;
926 _data[d].dmin = dd - min;
929 _data[e].dmin = ee - min2;
932 int w = _data[v].parent;
933 _data[v].successor = _data[w].successor;
934 _data[w].successor = -1;
935 _data[v].parent = _data[w].parent;
937 _data[w].left = _data[v].right;
939 if (_data[v].parent != -1){
940 if (_data[_data[v].parent].right == w) {
941 _data[_data[v].parent].right = v;
943 _data[_data[v].parent].left = v;
946 if (_data[w].left != -1){
947 _data[_data[w].left].parent = w;
954 Value min = _data[_data[v].parent].dmin;
956 int a = _data[v].parent;
957 Value aa = _data[a].dcost;
958 if (_tolerance.less(aa, _max_value)) {
963 Value ab = min + _data[b].dmin;
964 Value bb = _data[b].dcost;
965 if (_tolerance.less(bb, _max_value)) {
970 Value cc = _max_value;
971 if (_data[a].left != -1){
973 cc = min + _data[c].dmin;
977 Value dd = _max_value;
978 if (_data[v].right!=-1) {
981 if (_tolerance.less(dd, _max_value)) {
987 Value ee = _max_value;
988 if (_data[v].left != -1){
990 ee = ab + _data[e].dmin;
994 if (_tolerance.less(0, _data[b].dmin) ||
995 (e != -1 && !_tolerance.less(0, _data[e].dmin))) {
998 if (_tolerance.less(aa, cc)) {
999 if (_tolerance.less(aa, ee)) {
1004 } else if (_tolerance.less(cc, ee)) {
1010 _data[a].dcost = aa;
1011 if (_tolerance.less(aa, _max_value)) {
1012 _data[a].dcost -= min2;
1014 _data[a].dmin = min2;
1015 if (_tolerance.less(min2, _max_value)) {
1016 _data[a].dmin -= min;
1018 _data[b].dcost = bb;
1019 if (_tolerance.less(bb, _max_value)) {
1020 _data[b].dcost -= min;
1022 _data[b].dmin = min;
1024 _data[c].dmin = cc - min2;
1028 if (_tolerance.less(dd, _max_value)) {
1029 _data[d].dmin -= min;
1033 _data[e].dmin = ee - min2;
1036 int w = _data[v].parent;
1037 _data[v].successor = _data[w].successor;
1038 _data[w].successor = -1;
1039 _data[v].parent = _data[w].parent;
1040 _data[w].parent = v;
1041 _data[w].right = _data[v].left;
1043 if (_data[v].parent != -1){
1044 if (_data[_data[v].parent].left == w) {
1045 _data[_data[v].parent].left = v;
1047 _data[_data[v].parent].right = v;
1050 if (_data[w].right != -1){
1051 _data[_data[w].right].parent = w;
1068 ItemData(const Item &item)
1069 : id(item), successor(), parent(-1),
1070 left(-1), right(-1), dmin(0), dcost(0) {}