1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
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_UNION_FIND_H
20 #define LEMON_UNION_FIND_H
24 //!\brief Union-Find data structures.
33 #include <lemon/core.h>
39 /// \brief A \e Union-Find data structure implementation
41 /// The class implements the \e Union-Find data structure.
42 /// The union operation uses rank heuristic, while
43 /// the find operation uses path compression.
44 /// This is a very simple but efficient implementation, providing
45 /// only four methods: join (union), find, insert and size.
46 /// For more features see the \ref UnionFindEnum class.
48 /// It is primarily used in Kruskal algorithm for finding minimal
49 /// cost spanning tree in a graph.
52 /// \pre You need to add all the elements by the \ref insert()
54 template <typename _ItemIntMap>
58 typedef _ItemIntMap ItemIntMap;
59 typedef typename ItemIntMap::Key Item;
62 // If the items vector stores negative value for an item then
63 // that item is root item and it has -items[it] component size.
64 // Else the items[it] contains the index of the parent.
65 std::vector<int> items;
68 bool rep(int idx) const {
69 return items[idx] < 0;
72 int repIndex(int idx) const {
78 int next = items[idx];
79 const_cast<int&>(items[idx]) = k;
87 /// \brief Constructor
89 /// Constructor of the UnionFind class. You should give an item to
90 /// integer map which will be used from the data structure. If you
91 /// modify directly this map that may cause segmentation fault,
92 /// invalid data structure, or infinite loop when you use again
94 UnionFind(ItemIntMap& m) : index(m) {}
96 /// \brief Returns the index of the element's component.
98 /// The method returns the index of the element's component.
99 /// This is an integer between zero and the number of inserted elements.
101 int find(const Item& a) {
102 return repIndex(index[a]);
105 /// \brief Clears the union-find data structure
107 /// Erase each item from the data structure.
112 /// \brief Inserts a new element into the structure.
114 /// This method inserts a new element into the data structure.
116 /// The method returns the index of the new component.
117 int insert(const Item& a) {
118 int n = items.size();
124 /// \brief Joining the components of element \e a and element \e b.
126 /// This is the \e union operation of the Union-Find structure.
127 /// Joins the component of element \e a and component of
128 /// element \e b. If \e a and \e b are in the same component then
129 /// it returns false otherwise it returns true.
130 bool join(const Item& a, const Item& b) {
131 int ka = repIndex(index[a]);
132 int kb = repIndex(index[b]);
137 if (items[ka] < items[kb]) {
138 items[ka] += items[kb];
141 items[kb] += items[ka];
147 /// \brief Returns the size of the component of element \e a.
149 /// Returns the size of the component of element \e a.
150 int size(const Item& a) {
151 int k = repIndex(index[a]);
159 /// \brief A \e Union-Find data structure implementation which
160 /// is able to enumerate the components.
162 /// The class implements a \e Union-Find data structure
163 /// which is able to enumerate the components and the items in
164 /// a component. If you don't need this feature then perhaps it's
165 /// better to use the \ref UnionFind class which is more efficient.
167 /// The union operation uses rank heuristic, while
168 /// the find operation uses path compression.
170 /// \pre You need to add all the elements by the \ref insert()
173 template <typename _ItemIntMap>
174 class UnionFindEnum {
177 typedef _ItemIntMap ItemIntMap;
178 typedef typename ItemIntMap::Key Item;
184 // If the parent stores negative value for an item then that item
185 // is root item and it has ~(items[it].parent) component id. Else
186 // the items[it].parent contains the index of the parent.
188 // The \c next and \c prev provides the double-linked
189 // cyclic list of one component's items.
197 std::vector<ItemT> items;
206 std::vector<ClassT> classes;
207 int firstClass, firstFreeClass;
210 if (firstFreeClass == -1) {
211 int cdx = classes.size();
212 classes.push_back(ClassT());
215 int cdx = firstFreeClass;
216 firstFreeClass = classes[firstFreeClass].next;
222 if (firstFreeItem == -1) {
223 int idx = items.size();
224 items.push_back(ItemT());
227 int idx = firstFreeItem;
228 firstFreeItem = items[firstFreeItem].next;
234 bool rep(int idx) const {
235 return items[idx].parent < 0;
238 int repIndex(int idx) const {
244 int next = items[idx].parent;
245 const_cast<int&>(items[idx].parent) = k;
251 int classIndex(int idx) const {
252 return ~(items[repIndex(idx)].parent);
255 void singletonItem(int idx) {
256 items[idx].next = idx;
257 items[idx].prev = idx;
260 void laceItem(int idx, int rdx) {
261 items[idx].prev = rdx;
262 items[idx].next = items[rdx].next;
263 items[items[rdx].next].prev = idx;
264 items[rdx].next = idx;
267 void unlaceItem(int idx) {
268 items[items[idx].prev].next = items[idx].next;
269 items[items[idx].next].prev = items[idx].prev;
271 items[idx].next = firstFreeItem;
275 void spliceItems(int ak, int bk) {
276 items[items[ak].prev].next = bk;
277 items[items[bk].prev].next = ak;
278 int tmp = items[ak].prev;
279 items[ak].prev = items[bk].prev;
280 items[bk].prev = tmp;
284 void laceClass(int cls) {
285 if (firstClass != -1) {
286 classes[firstClass].prev = cls;
288 classes[cls].next = firstClass;
289 classes[cls].prev = -1;
293 void unlaceClass(int cls) {
294 if (classes[cls].prev != -1) {
295 classes[classes[cls].prev].next = classes[cls].next;
297 firstClass = classes[cls].next;
299 if (classes[cls].next != -1) {
300 classes[classes[cls].next].prev = classes[cls].prev;
303 classes[cls].next = firstFreeClass;
304 firstFreeClass = cls;
309 UnionFindEnum(ItemIntMap& _index)
310 : index(_index), items(), firstFreeItem(-1),
311 firstClass(-1), firstFreeClass(-1) {}
313 /// \brief Inserts the given element into a new component.
315 /// This method creates a new component consisting only of the
318 int insert(const Item& item) {
321 index.set(item, idx);
324 items[idx].item = item;
326 int cdx = newClass();
328 items[idx].parent = ~cdx;
331 classes[cdx].size = 1;
332 classes[cdx].firstItem = idx;
339 /// \brief Inserts the given element into the component of the others.
341 /// This methods inserts the element \e a into the component of the
343 void insert(const Item& item, int cls) {
344 int rdx = classes[cls].firstItem;
347 index.set(item, idx);
351 items[idx].item = item;
352 items[idx].parent = rdx;
354 ++classes[~(items[rdx].parent)].size;
357 /// \brief Clears the union-find data structure
359 /// Erase each item from the data structure.
366 /// \brief Finds the component of the given element.
368 /// The method returns the component id of the given element.
369 int find(const Item &item) const {
370 return ~(items[repIndex(index[item])].parent);
373 /// \brief Joining the component of element \e a and element \e b.
375 /// This is the \e union operation of the Union-Find structure.
376 /// Joins the component of element \e a and component of
377 /// element \e b. If \e a and \e b are in the same component then
378 /// returns -1 else returns the remaining class.
379 int join(const Item& a, const Item& b) {
381 int ak = repIndex(index[a]);
382 int bk = repIndex(index[b]);
388 int acx = ~(items[ak].parent);
389 int bcx = ~(items[bk].parent);
393 if (classes[acx].size > classes[bcx].size) {
394 classes[acx].size += classes[bcx].size;
395 items[bk].parent = ak;
399 classes[bcx].size += classes[acx].size;
400 items[ak].parent = bk;
409 /// \brief Returns the size of the class.
411 /// Returns the size of the class.
412 int size(int cls) const {
413 return classes[cls].size;
416 /// \brief Splits up the component.
418 /// Splitting the component into singleton components (component
420 void split(int cls) {
421 int fdx = classes[cls].firstItem;
422 int idx = items[fdx].next;
424 int next = items[idx].next;
428 int cdx = newClass();
429 items[idx].parent = ~cdx;
432 classes[cdx].size = 1;
433 classes[cdx].firstItem = idx;
438 items[idx].prev = idx;
439 items[idx].next = idx;
441 classes[~(items[idx].parent)].size = 1;
445 /// \brief Removes the given element from the structure.
447 /// Removes the element from its component and if the component becomes
448 /// empty then removes that component from the component list.
450 /// \warning It is an error to remove an element which is not in
452 /// \warning This running time of this operation is proportional to the
453 /// number of the items in this class.
454 void erase(const Item& item) {
455 int idx = index[item];
456 int fdx = items[idx].next;
458 int cdx = classIndex(idx);
461 items[idx].next = firstFreeItem;
465 classes[cdx].firstItem = fdx;
467 items[fdx].parent = ~cdx;
470 idx = items[fdx].next;
472 items[idx].parent = fdx;
473 idx = items[idx].next;
480 /// \brief Gives back a representant item of the component.
482 /// Gives back a representant item of the component.
483 Item item(int cls) const {
484 return items[classes[cls].firstItem].item;
487 /// \brief Removes the component of the given element from the structure.
489 /// Removes the component of the given element from the structure.
491 /// \warning It is an error to give an element which is not in the
493 void eraseClass(int cls) {
494 int fdx = classes[cls].firstItem;
496 items[items[fdx].prev].next = firstFreeItem;
500 /// \brief LEMON style iterator for the representant items.
502 /// ClassIt is a lemon style iterator for the components. It iterates
503 /// on the ids of the classes.
506 /// \brief Constructor of the iterator
508 /// Constructor of the iterator
509 ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
510 cdx = unionFind->firstClass;
513 /// \brief Constructor to get invalid iterator
515 /// Constructor to get invalid iterator
516 ClassIt(Invalid) : unionFind(0), cdx(-1) {}
518 /// \brief Increment operator
520 /// It steps to the next representant item.
521 ClassIt& operator++() {
522 cdx = unionFind->classes[cdx].next;
526 /// \brief Conversion operator
528 /// It converts the iterator to the current representant item.
529 operator int() const {
533 /// \brief Equality operator
535 /// Equality operator
536 bool operator==(const ClassIt& i) {
540 /// \brief Inequality operator
542 /// Inequality operator
543 bool operator!=(const ClassIt& i) {
548 const UnionFindEnum* unionFind;
552 /// \brief LEMON style iterator for the items of a component.
554 /// ClassIt is a lemon style iterator for the components. It iterates
555 /// on the items of a class. By example if you want to iterate on
556 /// each items of each classes then you may write the next code.
558 /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
559 /// std::cout << "Class: ";
560 /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
561 /// std::cout << toString(iit) << ' ' << std::endl;
563 /// std::cout << std::endl;
568 /// \brief Constructor of the iterator
570 /// Constructor of the iterator. The iterator iterates
571 /// on the class of the \c item.
572 ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
573 fdx = idx = unionFind->classes[cls].firstItem;
576 /// \brief Constructor to get invalid iterator
578 /// Constructor to get invalid iterator
579 ItemIt(Invalid) : unionFind(0), idx(-1) {}
581 /// \brief Increment operator
583 /// It steps to the next item in the class.
584 ItemIt& operator++() {
585 idx = unionFind->items[idx].next;
586 if (idx == fdx) idx = -1;
590 /// \brief Conversion operator
592 /// It converts the iterator to the current item.
593 operator const Item&() const {
594 return unionFind->items[idx].item;
597 /// \brief Equality operator
599 /// Equality operator
600 bool operator==(const ItemIt& i) {
604 /// \brief Inequality operator
606 /// Inequality operator
607 bool operator!=(const ItemIt& i) {
612 const UnionFindEnum* unionFind;
620 /// \brief A \e Extend-Find data structure implementation which
621 /// is able to enumerate the components.
623 /// The class implements an \e Extend-Find data structure which is
624 /// able to enumerate the components and the items in a
625 /// component. The data structure is a simplification of the
626 /// Union-Find structure, and it does not allow to merge two components.
628 /// \pre You need to add all the elements by the \ref insert()
630 template <typename _ItemIntMap>
631 class ExtendFindEnum {
634 typedef _ItemIntMap ItemIntMap;
635 typedef typename ItemIntMap::Key Item;
647 std::vector<ItemT> items;
655 std::vector<ClassT> classes;
657 int firstClass, firstFreeClass;
660 if (firstFreeClass != -1) {
661 int cdx = firstFreeClass;
662 firstFreeClass = classes[cdx].next;
665 classes.push_back(ClassT());
666 return classes.size() - 1;
671 if (firstFreeItem != -1) {
672 int idx = firstFreeItem;
673 firstFreeItem = items[idx].next;
676 items.push_back(ItemT());
677 return items.size() - 1;
683 /// \brief Constructor
684 ExtendFindEnum(ItemIntMap& _index)
685 : index(_index), items(), firstFreeItem(-1),
686 classes(), firstClass(-1), firstFreeClass(-1) {}
688 /// \brief Inserts the given element into a new component.
690 /// This method creates a new component consisting only of the
692 int insert(const Item& item) {
693 int cdx = newClass();
694 classes[cdx].prev = -1;
695 classes[cdx].next = firstClass;
696 if (firstClass != -1) {
697 classes[firstClass].prev = cdx;
702 items[idx].item = item;
703 items[idx].cls = cdx;
704 items[idx].prev = idx;
705 items[idx].next = idx;
707 classes[cdx].firstItem = idx;
709 index.set(item, idx);
714 /// \brief Inserts the given element into the given component.
716 /// This methods inserts the element \e item a into the \e cls class.
717 void insert(const Item& item, int cls) {
719 int rdx = classes[cls].firstItem;
720 items[idx].item = item;
721 items[idx].cls = cls;
723 items[idx].prev = rdx;
724 items[idx].next = items[rdx].next;
725 items[items[rdx].next].prev = idx;
726 items[rdx].next = idx;
728 index.set(item, idx);
731 /// \brief Clears the union-find data structure
733 /// Erase each item from the data structure.
737 firstClass = firstFreeClass = firstFreeItem = -1;
740 /// \brief Gives back the class of the \e item.
742 /// Gives back the class of the \e item.
743 int find(const Item &item) const {
744 return items[index[item]].cls;
747 /// \brief Gives back a representant item of the component.
749 /// Gives back a representant item of the component.
750 Item item(int cls) const {
751 return items[classes[cls].firstItem].item;
754 /// \brief Removes the given element from the structure.
756 /// Removes the element from its component and if the component becomes
757 /// empty then removes that component from the component list.
759 /// \warning It is an error to remove an element which is not in
761 void erase(const Item &item) {
762 int idx = index[item];
763 int cdx = items[idx].cls;
765 if (idx == items[idx].next) {
766 if (classes[cdx].prev != -1) {
767 classes[classes[cdx].prev].next = classes[cdx].next;
769 firstClass = classes[cdx].next;
771 if (classes[cdx].next != -1) {
772 classes[classes[cdx].next].prev = classes[cdx].prev;
774 classes[cdx].next = firstFreeClass;
775 firstFreeClass = cdx;
777 classes[cdx].firstItem = items[idx].next;
778 items[items[idx].next].prev = items[idx].prev;
779 items[items[idx].prev].next = items[idx].next;
781 items[idx].next = firstFreeItem;
787 /// \brief Removes the component of the given element from the structure.
789 /// Removes the component of the given element from the structure.
791 /// \warning It is an error to give an element which is not in the
793 void eraseClass(int cdx) {
794 int idx = classes[cdx].firstItem;
795 items[items[idx].prev].next = firstFreeItem;
798 if (classes[cdx].prev != -1) {
799 classes[classes[cdx].prev].next = classes[cdx].next;
801 firstClass = classes[cdx].next;
803 if (classes[cdx].next != -1) {
804 classes[classes[cdx].next].prev = classes[cdx].prev;
806 classes[cdx].next = firstFreeClass;
807 firstFreeClass = cdx;
810 /// \brief LEMON style iterator for the classes.
812 /// ClassIt is a lemon style iterator for the components. It iterates
813 /// on the ids of classes.
816 /// \brief Constructor of the iterator
818 /// Constructor of the iterator
819 ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
820 cdx = extendFind->firstClass;
823 /// \brief Constructor to get invalid iterator
825 /// Constructor to get invalid iterator
826 ClassIt(Invalid) : extendFind(0), cdx(-1) {}
828 /// \brief Increment operator
830 /// It steps to the next representant item.
831 ClassIt& operator++() {
832 cdx = extendFind->classes[cdx].next;
836 /// \brief Conversion operator
838 /// It converts the iterator to the current class id.
839 operator int() const {
843 /// \brief Equality operator
845 /// Equality operator
846 bool operator==(const ClassIt& i) {
850 /// \brief Inequality operator
852 /// Inequality operator
853 bool operator!=(const ClassIt& i) {
858 const ExtendFindEnum* extendFind;
862 /// \brief LEMON style iterator for the items of a component.
864 /// ClassIt is a lemon style iterator for the components. It iterates
865 /// on the items of a class. By example if you want to iterate on
866 /// each items of each classes then you may write the next code.
868 /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
869 /// std::cout << "Class: ";
870 /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
871 /// std::cout << toString(iit) << ' ' << std::endl;
873 /// std::cout << std::endl;
878 /// \brief Constructor of the iterator
880 /// Constructor of the iterator. The iterator iterates
881 /// on the class of the \c item.
882 ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
883 fdx = idx = extendFind->classes[cls].firstItem;
886 /// \brief Constructor to get invalid iterator
888 /// Constructor to get invalid iterator
889 ItemIt(Invalid) : extendFind(0), idx(-1) {}
891 /// \brief Increment operator
893 /// It steps to the next item in the class.
894 ItemIt& operator++() {
895 idx = extendFind->items[idx].next;
896 if (fdx == idx) idx = -1;
900 /// \brief Conversion operator
902 /// It converts the iterator to the current item.
903 operator const Item&() const {
904 return extendFind->items[idx].item;
907 /// \brief Equality operator
909 /// Equality operator
910 bool operator==(const ItemIt& i) {
914 /// \brief Inequality operator
916 /// Inequality operator
917 bool operator!=(const ItemIt& i) {
922 const ExtendFindEnum* extendFind;
930 /// \brief A \e Union-Find data structure implementation which
931 /// is able to store a priority for each item and retrieve the minimum of
934 /// A \e Union-Find data structure implementation which is able to
935 /// store a priority for each item and retrieve the minimum of each
936 /// class. In addition, it supports the joining and splitting the
937 /// components. If you don't need this feature then you makes
938 /// better to use the \ref UnionFind class which is more efficient.
940 /// The union-find data strcuture based on a (2, 16)-tree with a
941 /// tournament minimum selection on the internal nodes. The insert
942 /// operation takes O(1), the find, set, decrease and increase takes
943 /// O(log(n)), where n is the number of nodes in the current
944 /// component. The complexity of join and split is O(log(n)*k),
945 /// where n is the sum of the number of the nodes and k is the
946 /// number of joined components or the number of the components
949 /// \pre You need to add all the elements by the \ref insert()
952 template <typename _Value, typename _ItemIntMap,
953 typename _Comp = std::less<_Value> >
954 class HeapUnionFind {
957 typedef _Value Value;
958 typedef typename _ItemIntMap::Key Item;
960 typedef _ItemIntMap ItemIntMap;
966 static const int cmax = 16;
979 int first_free_class;
980 std::vector<ClassNode> classes;
983 if (first_free_class < 0) {
984 int id = classes.size();
985 classes.push_back(ClassNode());
988 int id = first_free_class;
989 first_free_class = classes[id].next;
994 void deleteClass(int id) {
995 classes[id].next = first_free_class;
996 first_free_class = id;
1008 int first_free_node;
1009 std::vector<ItemNode> nodes;
1012 if (first_free_node < 0) {
1013 int id = nodes.size();
1014 nodes.push_back(ItemNode());
1017 int id = first_free_node;
1018 first_free_node = nodes[id].next;
1023 void deleteNode(int id) {
1024 nodes[id].next = first_free_node;
1025 first_free_node = id;
1030 int findClass(int id) const {
1033 kd = nodes[kd].parent;
1038 int leftNode(int id) const {
1039 int kd = ~(classes[id].parent);
1040 for (int i = 0; i < classes[id].depth; ++i) {
1041 kd = nodes[kd].left;
1046 int nextNode(int id) const {
1048 while (id >= 0 && nodes[id].next == -1) {
1049 id = nodes[id].parent;
1055 id = nodes[id].next;
1057 id = nodes[id].left;
1063 void setPrio(int id) {
1064 int jd = nodes[id].left;
1065 nodes[id].prio = nodes[jd].prio;
1066 nodes[id].item = nodes[jd].item;
1067 jd = nodes[jd].next;
1069 if (comp(nodes[jd].prio, nodes[id].prio)) {
1070 nodes[id].prio = nodes[jd].prio;
1071 nodes[id].item = nodes[jd].item;
1073 jd = nodes[jd].next;
1077 void push(int id, int jd) {
1079 nodes[id].left = nodes[id].right = jd;
1080 nodes[jd].next = nodes[jd].prev = -1;
1081 nodes[jd].parent = id;
1084 void pushAfter(int id, int jd) {
1085 int kd = nodes[id].parent;
1086 if (nodes[id].next != -1) {
1087 nodes[nodes[id].next].prev = jd;
1089 nodes[kd].size += 1;
1093 nodes[kd].right = jd;
1094 nodes[kd].size += 1;
1097 nodes[jd].next = nodes[id].next;
1098 nodes[jd].prev = id;
1099 nodes[id].next = jd;
1100 nodes[jd].parent = kd;
1103 void pushRight(int id, int jd) {
1104 nodes[id].size += 1;
1105 nodes[jd].prev = nodes[id].right;
1106 nodes[jd].next = -1;
1107 nodes[nodes[id].right].next = jd;
1108 nodes[id].right = jd;
1109 nodes[jd].parent = id;
1112 void popRight(int id) {
1113 nodes[id].size -= 1;
1114 int jd = nodes[id].right;
1115 nodes[nodes[jd].prev].next = -1;
1116 nodes[id].right = nodes[jd].prev;
1119 void splice(int id, int jd) {
1120 nodes[id].size += nodes[jd].size;
1121 nodes[nodes[id].right].next = nodes[jd].left;
1122 nodes[nodes[jd].left].prev = nodes[id].right;
1123 int kd = nodes[jd].left;
1125 nodes[kd].parent = id;
1126 kd = nodes[kd].next;
1128 nodes[id].right = nodes[jd].right;
1131 void split(int id, int jd) {
1132 int kd = nodes[id].parent;
1133 nodes[kd].right = nodes[id].prev;
1134 nodes[nodes[id].prev].next = -1;
1136 nodes[jd].left = id;
1137 nodes[id].prev = -1;
1140 nodes[id].parent = jd;
1141 nodes[jd].right = id;
1142 id = nodes[id].next;
1145 nodes[kd].size -= num;
1146 nodes[jd].size = num;
1149 void pushLeft(int id, int jd) {
1150 nodes[id].size += 1;
1151 nodes[jd].next = nodes[id].left;
1152 nodes[jd].prev = -1;
1153 nodes[nodes[id].left].prev = jd;
1154 nodes[id].left = jd;
1155 nodes[jd].parent = id;
1158 void popLeft(int id) {
1159 nodes[id].size -= 1;
1160 int jd = nodes[id].left;
1161 nodes[nodes[jd].next].prev = -1;
1162 nodes[id].left = nodes[jd].next;
1165 void repairLeft(int id) {
1166 int jd = ~(classes[id].parent);
1167 while (nodes[jd].left != -1) {
1168 int kd = nodes[jd].left;
1169 if (nodes[jd].size == 1) {
1170 if (nodes[jd].parent < 0) {
1171 classes[id].parent = ~kd;
1172 classes[id].depth -= 1;
1173 nodes[kd].parent = ~id;
1177 int pd = nodes[jd].parent;
1178 if (nodes[nodes[jd].next].size < cmax) {
1179 pushLeft(nodes[jd].next, nodes[jd].left);
1180 if (less(nodes[jd].left, nodes[jd].next)) {
1181 nodes[nodes[jd].next].prio = nodes[nodes[jd].left].prio;
1182 nodes[nodes[jd].next].item = nodes[nodes[jd].left].item;
1188 int ld = nodes[nodes[jd].next].left;
1189 popLeft(nodes[jd].next);
1191 if (less(ld, nodes[jd].left)) {
1192 nodes[jd].item = nodes[ld].item;
1193 nodes[jd].prio = nodes[jd].prio;
1195 if (nodes[nodes[jd].next].item == nodes[ld].item) {
1196 setPrio(nodes[jd].next);
1198 jd = nodes[jd].left;
1202 jd = nodes[jd].left;
1207 void repairRight(int id) {
1208 int jd = ~(classes[id].parent);
1209 while (nodes[jd].right != -1) {
1210 int kd = nodes[jd].right;
1211 if (nodes[jd].size == 1) {
1212 if (nodes[jd].parent < 0) {
1213 classes[id].parent = ~kd;
1214 classes[id].depth -= 1;
1215 nodes[kd].parent = ~id;
1219 int pd = nodes[jd].parent;
1220 if (nodes[nodes[jd].prev].size < cmax) {
1221 pushRight(nodes[jd].prev, nodes[jd].right);
1222 if (less(nodes[jd].right, nodes[jd].prev)) {
1223 nodes[nodes[jd].prev].prio = nodes[nodes[jd].right].prio;
1224 nodes[nodes[jd].prev].item = nodes[nodes[jd].right].item;
1230 int ld = nodes[nodes[jd].prev].right;
1231 popRight(nodes[jd].prev);
1233 if (less(ld, nodes[jd].right)) {
1234 nodes[jd].item = nodes[ld].item;
1235 nodes[jd].prio = nodes[jd].prio;
1237 if (nodes[nodes[jd].prev].item == nodes[ld].item) {
1238 setPrio(nodes[jd].prev);
1240 jd = nodes[jd].right;
1244 jd = nodes[jd].right;
1250 bool less(int id, int jd) const {
1251 return comp(nodes[id].prio, nodes[jd].prio);
1254 bool equal(int id, int jd) const {
1255 return !less(id, jd) && !less(jd, id);
1261 /// \brief Returns true when the given class is alive.
1263 /// Returns true when the given class is alive, ie. the class is
1264 /// not nested into other class.
1265 bool alive(int cls) const {
1266 return classes[cls].parent < 0;
1269 /// \brief Returns true when the given class is trivial.
1271 /// Returns true when the given class is trivial, ie. the class
1272 /// contains just one item directly.
1273 bool trivial(int cls) const {
1274 return classes[cls].left == -1;
1277 /// \brief Constructs the union-find.
1279 /// Constructs the union-find.
1280 /// \brief _index The index map of the union-find. The data
1281 /// structure uses internally for store references.
1282 HeapUnionFind(ItemIntMap& _index)
1283 : index(_index), first_class(-1),
1284 first_free_class(-1), first_free_node(-1) {}
1286 /// \brief Insert a new node into a new component.
1288 /// Insert a new node into a new component.
1289 /// \param item The item of the new node.
1290 /// \param prio The priority of the new node.
1291 /// \return The class id of the one-item-heap.
1292 int insert(const Item& item, const Value& prio) {
1294 nodes[id].item = item;
1295 nodes[id].prio = prio;
1298 nodes[id].prev = -1;
1299 nodes[id].next = -1;
1301 nodes[id].left = -1;
1302 nodes[id].right = -1;
1304 nodes[id].item = item;
1307 int class_id = newClass();
1308 classes[class_id].parent = ~id;
1309 classes[class_id].depth = 0;
1311 classes[class_id].left = -1;
1312 classes[class_id].right = -1;
1314 if (first_class != -1) {
1315 classes[first_class].prev = class_id;
1317 classes[class_id].next = first_class;
1318 classes[class_id].prev = -1;
1319 first_class = class_id;
1321 nodes[id].parent = ~class_id;
1326 /// \brief The class of the item.
1328 /// \return The alive class id of the item, which is not nested into
1331 /// The time complexity is O(log(n)).
1332 int find(const Item& item) const {
1333 return findClass(index[item]);
1336 /// \brief Joins the classes.
1338 /// The current function joins the given classes. The parameter is
1339 /// an STL range which should be contains valid class ids. The
1340 /// time complexity is O(log(n)*k) where n is the overall number
1341 /// of the joined nodes and k is the number of classes.
1342 /// \return The class of the joined classes.
1343 /// \pre The range should contain at least two class ids.
1344 template <typename Iterator>
1345 int join(Iterator begin, Iterator end) {
1346 std::vector<int> cs;
1347 for (Iterator it = begin; it != end; ++it) {
1351 int class_id = newClass();
1352 { // creation union-find
1354 if (first_class != -1) {
1355 classes[first_class].prev = class_id;
1357 classes[class_id].next = first_class;
1358 classes[class_id].prev = -1;
1359 first_class = class_id;
1361 classes[class_id].depth = classes[cs[0]].depth;
1362 classes[class_id].parent = classes[cs[0]].parent;
1363 nodes[~(classes[class_id].parent)].parent = ~class_id;
1367 classes[class_id].left = l;
1368 classes[class_id].right = l;
1370 if (classes[l].next != -1) {
1371 classes[classes[l].next].prev = classes[l].prev;
1373 classes[classes[l].prev].next = classes[l].next;
1375 classes[l].prev = -1;
1376 classes[l].next = -1;
1378 classes[l].depth = leftNode(l);
1379 classes[l].parent = class_id;
1383 { // merging of heap
1385 for (int ci = 1; ci < int(cs.size()); ++ci) {
1387 int rln = leftNode(r);
1388 if (classes[l].depth > classes[r].depth) {
1389 int id = ~(classes[l].parent);
1390 for (int i = classes[r].depth + 1; i < classes[l].depth; ++i) {
1391 id = nodes[id].right;
1393 while (id >= 0 && nodes[id].size == cmax) {
1394 int new_id = newNode();
1395 int right_id = nodes[id].right;
1398 if (nodes[id].item == nodes[right_id].item) {
1401 push(new_id, right_id);
1402 pushRight(new_id, ~(classes[r].parent));
1405 id = nodes[id].parent;
1406 classes[r].parent = ~new_id;
1409 int new_parent = newNode();
1410 nodes[new_parent].next = -1;
1411 nodes[new_parent].prev = -1;
1412 nodes[new_parent].parent = ~l;
1414 push(new_parent, ~(classes[l].parent));
1415 pushRight(new_parent, ~(classes[r].parent));
1416 setPrio(new_parent);
1418 classes[l].parent = ~new_parent;
1419 classes[l].depth += 1;
1421 pushRight(id, ~(classes[r].parent));
1422 while (id >= 0 && less(~(classes[r].parent), id)) {
1423 nodes[id].prio = nodes[~(classes[r].parent)].prio;
1424 nodes[id].item = nodes[~(classes[r].parent)].item;
1425 id = nodes[id].parent;
1428 } else if (classes[r].depth > classes[l].depth) {
1429 int id = ~(classes[r].parent);
1430 for (int i = classes[l].depth + 1; i < classes[r].depth; ++i) {
1431 id = nodes[id].left;
1433 while (id >= 0 && nodes[id].size == cmax) {
1434 int new_id = newNode();
1435 int left_id = nodes[id].left;
1438 if (nodes[id].prio == nodes[left_id].prio) {
1441 push(new_id, left_id);
1442 pushLeft(new_id, ~(classes[l].parent));
1445 id = nodes[id].parent;
1446 classes[l].parent = ~new_id;
1450 int new_parent = newNode();
1451 nodes[new_parent].next = -1;
1452 nodes[new_parent].prev = -1;
1453 nodes[new_parent].parent = ~l;
1455 push(new_parent, ~(classes[r].parent));
1456 pushLeft(new_parent, ~(classes[l].parent));
1457 setPrio(new_parent);
1459 classes[r].parent = ~new_parent;
1460 classes[r].depth += 1;
1462 pushLeft(id, ~(classes[l].parent));
1463 while (id >= 0 && less(~(classes[l].parent), id)) {
1464 nodes[id].prio = nodes[~(classes[l].parent)].prio;
1465 nodes[id].item = nodes[~(classes[l].parent)].item;
1466 id = nodes[id].parent;
1469 nodes[~(classes[r].parent)].parent = ~l;
1470 classes[l].parent = classes[r].parent;
1471 classes[l].depth = classes[r].depth;
1473 if (classes[l].depth != 0 &&
1474 nodes[~(classes[l].parent)].size +
1475 nodes[~(classes[r].parent)].size <= cmax) {
1476 splice(~(classes[l].parent), ~(classes[r].parent));
1477 deleteNode(~(classes[r].parent));
1478 if (less(~(classes[r].parent), ~(classes[l].parent))) {
1479 nodes[~(classes[l].parent)].prio =
1480 nodes[~(classes[r].parent)].prio;
1481 nodes[~(classes[l].parent)].item =
1482 nodes[~(classes[r].parent)].item;
1485 int new_parent = newNode();
1486 nodes[new_parent].next = nodes[new_parent].prev = -1;
1487 push(new_parent, ~(classes[l].parent));
1488 pushRight(new_parent, ~(classes[r].parent));
1489 setPrio(new_parent);
1491 classes[l].parent = ~new_parent;
1492 classes[l].depth += 1;
1493 nodes[new_parent].parent = ~l;
1496 if (classes[r].next != -1) {
1497 classes[classes[r].next].prev = classes[r].prev;
1499 classes[classes[r].prev].next = classes[r].next;
1501 classes[r].prev = classes[l].right;
1502 classes[classes[l].right].next = r;
1503 classes[l].right = r;
1504 classes[r].parent = l;
1506 classes[r].next = -1;
1507 classes[r].depth = rln;
1513 /// \brief Split the class to subclasses.
1515 /// The current function splits the given class. The join, which
1516 /// made the current class, stored a reference to the
1517 /// subclasses. The \c splitClass() member restores the classes
1518 /// and creates the heaps. The parameter is an STL output iterator
1519 /// which will be filled with the subclass ids. The time
1520 /// complexity is O(log(n)*k) where n is the overall number of
1521 /// nodes in the splitted classes and k is the number of the
1523 template <typename Iterator>
1524 void split(int cls, Iterator out) {
1525 std::vector<int> cs;
1526 { // splitting union-find
1528 int l = classes[id].left;
1530 classes[l].parent = classes[id].parent;
1531 classes[l].depth = classes[id].depth;
1533 nodes[~(classes[l].parent)].parent = ~l;
1539 l = classes[l].next;
1542 classes[classes[id].right].next = first_class;
1543 classes[first_class].prev = classes[id].right;
1544 first_class = classes[id].left;
1546 if (classes[id].next != -1) {
1547 classes[classes[id].next].prev = classes[id].prev;
1549 classes[classes[id].prev].next = classes[id].next;
1555 for (int i = 1; i < int(cs.size()); ++i) {
1556 int l = classes[cs[i]].depth;
1557 while (nodes[nodes[l].parent].left == l) {
1558 l = nodes[l].parent;
1561 while (nodes[l].parent >= 0) {
1562 l = nodes[l].parent;
1563 int new_node = newNode();
1565 nodes[new_node].prev = -1;
1566 nodes[new_node].next = -1;
1569 pushAfter(l, new_node);
1574 classes[cs[i]].parent = ~r;
1575 classes[cs[i]].depth = classes[~(nodes[l].parent)].depth;
1576 nodes[r].parent = ~cs[i];
1581 repairRight(~(nodes[l].parent));
1589 /// \brief Gives back the priority of the current item.
1591 /// \return Gives back the priority of the current item.
1592 const Value& operator[](const Item& item) const {
1593 return nodes[index[item]].prio;
1596 /// \brief Sets the priority of the current item.
1598 /// Sets the priority of the current item.
1599 void set(const Item& item, const Value& prio) {
1600 if (comp(prio, nodes[index[item]].prio)) {
1601 decrease(item, prio);
1602 } else if (!comp(prio, nodes[index[item]].prio)) {
1603 increase(item, prio);
1607 /// \brief Increase the priority of the current item.
1609 /// Increase the priority of the current item.
1610 void increase(const Item& item, const Value& prio) {
1611 int id = index[item];
1612 int kd = nodes[id].parent;
1613 nodes[id].prio = prio;
1614 while (kd >= 0 && nodes[kd].item == item) {
1616 kd = nodes[kd].parent;
1620 /// \brief Increase the priority of the current item.
1622 /// Increase the priority of the current item.
1623 void decrease(const Item& item, const Value& prio) {
1624 int id = index[item];
1625 int kd = nodes[id].parent;
1626 nodes[id].prio = prio;
1627 while (kd >= 0 && less(id, kd)) {
1628 nodes[kd].prio = prio;
1629 nodes[kd].item = item;
1630 kd = nodes[kd].parent;
1634 /// \brief Gives back the minimum priority of the class.
1636 /// \return Gives back the minimum priority of the class.
1637 const Value& classPrio(int cls) const {
1638 return nodes[~(classes[cls].parent)].prio;
1641 /// \brief Gives back the minimum priority item of the class.
1643 /// \return Gives back the minimum priority item of the class.
1644 const Item& classTop(int cls) const {
1645 return nodes[~(classes[cls].parent)].item;
1648 /// \brief Gives back a representant item of the class.
1650 /// The representant is indpendent from the priorities of the
1652 /// \return Gives back a representant item of the class.
1653 const Item& classRep(int id) const {
1654 int parent = classes[id].parent;
1655 return nodes[parent >= 0 ? classes[id].depth : leftNode(id)].item;
1658 /// \brief LEMON style iterator for the items of a class.
1660 /// ClassIt is a lemon style iterator for the components. It iterates
1661 /// on the items of a class. By example if you want to iterate on
1662 /// each items of each classes then you may write the next code.
1664 /// for (ClassIt cit(huf); cit != INVALID; ++cit) {
1665 /// std::cout << "Class: ";
1666 /// for (ItemIt iit(huf, cit); iit != INVALID; ++iit) {
1667 /// std::cout << toString(iit) << ' ' << std::endl;
1669 /// std::cout << std::endl;
1675 const HeapUnionFind* _huf;
1680 /// \brief Default constructor
1682 /// Default constructor
1685 ItemIt(const HeapUnionFind& huf, int cls) : _huf(&huf) {
1687 int parent = _huf->classes[id].parent;
1689 _id = _huf->classes[id].depth;
1690 if (_huf->classes[id].next != -1) {
1691 _lid = _huf->classes[_huf->classes[id].next].depth;
1696 _id = _huf->leftNode(id);
1701 /// \brief Increment operator
1703 /// It steps to the next item in the class.
1704 ItemIt& operator++() {
1705 _id = _huf->nextNode(_id);
1709 /// \brief Conversion operator
1711 /// It converts the iterator to the current item.
1712 operator const Item&() const {
1713 return _huf->nodes[_id].item;
1716 /// \brief Equality operator
1718 /// Equality operator
1719 bool operator==(const ItemIt& i) {
1720 return i._id == _id;
1723 /// \brief Inequality operator
1725 /// Inequality operator
1726 bool operator!=(const ItemIt& i) {
1727 return i._id != _id;
1730 /// \brief Equality operator
1732 /// Equality operator
1733 bool operator==(Invalid) {
1737 /// \brief Inequality operator
1739 /// Inequality operator
1740 bool operator!=(Invalid) {
1746 /// \brief Class iterator
1748 /// The iterator stores
1752 const HeapUnionFind* _huf;
1757 ClassIt(const HeapUnionFind& huf)
1758 : _huf(&huf), _id(huf.first_class) {}
1760 ClassIt(const HeapUnionFind& huf, int cls)
1761 : _huf(&huf), _id(huf.classes[cls].left) {}
1763 ClassIt(Invalid) : _huf(0), _id(-1) {}
1765 const ClassIt& operator++() {
1766 _id = _huf->classes[_id].next;
1770 /// \brief Equality operator
1772 /// Equality operator
1773 bool operator==(const ClassIt& i) {
1774 return i._id == _id;
1777 /// \brief Inequality operator
1779 /// Inequality operator
1780 bool operator!=(const ClassIt& i) {
1781 return i._id != _id;
1784 operator int() const {
1796 #endif //LEMON_UNION_FIND_H