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
19 #ifndef LEMON_UNION_FIND_H
20 #define LEMON_UNION_FIND_H
24 //!\brief Union-Find data structures.
32 #include <lemon/bits/invalid.h>
38 /// \brief A \e Union-Find data structure implementation
40 /// The class implements the \e Union-Find data structure.
41 /// The union operation uses rank heuristic, while
42 /// the find operation uses path compression.
43 /// This is a very simple but efficient implementation, providing
44 /// only four methods: join (union), find, insert and size.
45 /// For more features see the \ref UnionFindEnum class.
47 /// It is primarily used in Kruskal algorithm for finding minimal
48 /// cost spanning tree in a graph.
51 /// \pre You need to add all the elements by the \ref insert()
53 template <typename _ItemIntMap>
57 typedef _ItemIntMap ItemIntMap;
58 typedef typename ItemIntMap::Key Item;
61 // If the items vector stores negative value for an item then
62 // that item is root item and it has -items[it] component size.
63 // Else the items[it] contains the index of the parent.
64 std::vector<int> items;
67 bool rep(int idx) const {
68 return items[idx] < 0;
71 int repIndex(int idx) const {
77 int next = items[idx];
78 const_cast<int&>(items[idx]) = k;
86 /// \brief Constructor
88 /// Constructor of the UnionFind class. You should give an item to
89 /// integer map which will be used from the data structure. If you
90 /// modify directly this map that may cause segmentation fault,
91 /// invalid data structure, or infinite loop when you use again
93 UnionFind(ItemIntMap& m) : index(m) {}
95 /// \brief Returns the index of the element's component.
97 /// The method returns the index of the element's component.
98 /// This is an integer between zero and the number of inserted elements.
100 int find(const Item& a) {
101 return repIndex(index[a]);
104 /// \brief Clears the union-find data structure
106 /// Erase each item from the data structure.
111 /// \brief Inserts a new element into the structure.
113 /// This method inserts a new element into the data structure.
115 /// The method returns the index of the new component.
116 int insert(const Item& a) {
117 int n = items.size();
123 /// \brief Joining the components of element \e a and element \e b.
125 /// This is the \e union operation of the Union-Find structure.
126 /// Joins the component of element \e a and component of
127 /// element \e b. If \e a and \e b are in the same component then
128 /// it returns false otherwise it returns true.
129 bool join(const Item& a, const Item& b) {
130 int ka = repIndex(index[a]);
131 int kb = repIndex(index[b]);
136 if (items[ka] < items[kb]) {
137 items[ka] += items[kb];
140 items[kb] += items[ka];
146 /// \brief Returns the size of the component of element \e a.
148 /// Returns the size of the component of element \e a.
149 int size(const Item& a) {
150 int k = repIndex(index[a]);
158 /// \brief A \e Union-Find data structure implementation which
159 /// is able to enumerate the components.
161 /// The class implements a \e Union-Find data structure
162 /// which is able to enumerate the components and the items in
163 /// a component. If you don't need this feature then perhaps it's
164 /// better to use the \ref UnionFind class which is more efficient.
166 /// The union operation uses rank heuristic, while
167 /// the find operation uses path compression.
169 /// \pre You need to add all the elements by the \ref insert()
172 template <typename _ItemIntMap>
173 class UnionFindEnum {
176 typedef _ItemIntMap ItemIntMap;
177 typedef typename ItemIntMap::Key Item;
183 // If the parent stores negative value for an item then that item
184 // is root item and it has ~(items[it].parent) component id. Else
185 // the items[it].parent contains the index of the parent.
187 // The \c next and \c prev provides the double-linked
188 // cyclic list of one component's items.
196 std::vector<ItemT> items;
205 std::vector<ClassT> classes;
206 int firstClass, firstFreeClass;
209 if (firstFreeClass == -1) {
210 int cdx = classes.size();
211 classes.push_back(ClassT());
214 int cdx = firstFreeClass;
215 firstFreeClass = classes[firstFreeClass].next;
221 if (firstFreeItem == -1) {
222 int idx = items.size();
223 items.push_back(ItemT());
226 int idx = firstFreeItem;
227 firstFreeItem = items[firstFreeItem].next;
233 bool rep(int idx) const {
234 return items[idx].parent < 0;
237 int repIndex(int idx) const {
243 int next = items[idx].parent;
244 const_cast<int&>(items[idx].parent) = k;
250 int classIndex(int idx) const {
251 return ~(items[repIndex(idx)].parent);
254 void singletonItem(int idx) {
255 items[idx].next = idx;
256 items[idx].prev = idx;
259 void laceItem(int idx, int rdx) {
260 items[idx].prev = rdx;
261 items[idx].next = items[rdx].next;
262 items[items[rdx].next].prev = idx;
263 items[rdx].next = idx;
266 void unlaceItem(int idx) {
267 items[items[idx].prev].next = items[idx].next;
268 items[items[idx].next].prev = items[idx].prev;
270 items[idx].next = firstFreeItem;
274 void spliceItems(int ak, int bk) {
275 items[items[ak].prev].next = bk;
276 items[items[bk].prev].next = ak;
277 int tmp = items[ak].prev;
278 items[ak].prev = items[bk].prev;
279 items[bk].prev = tmp;
283 void laceClass(int cls) {
284 if (firstClass != -1) {
285 classes[firstClass].prev = cls;
287 classes[cls].next = firstClass;
288 classes[cls].prev = -1;
292 void unlaceClass(int cls) {
293 if (classes[cls].prev != -1) {
294 classes[classes[cls].prev].next = classes[cls].next;
296 firstClass = classes[cls].next;
298 if (classes[cls].next != -1) {
299 classes[classes[cls].next].prev = classes[cls].prev;
302 classes[cls].next = firstFreeClass;
303 firstFreeClass = cls;
308 UnionFindEnum(ItemIntMap& _index)
309 : index(_index), items(), firstFreeItem(-1),
310 firstClass(-1), firstFreeClass(-1) {}
312 /// \brief Inserts the given element into a new component.
314 /// This method creates a new component consisting only of the
317 int insert(const Item& item) {
320 index.set(item, idx);
323 items[idx].item = item;
325 int cdx = newClass();
327 items[idx].parent = ~cdx;
330 classes[cdx].size = 1;
331 classes[cdx].firstItem = idx;
338 /// \brief Inserts the given element into the component of the others.
340 /// This methods inserts the element \e a into the component of the
342 void insert(const Item& item, int cls) {
343 int rdx = classes[cls].firstItem;
346 index.set(item, idx);
350 items[idx].item = item;
351 items[idx].parent = rdx;
353 ++classes[~(items[rdx].parent)].size;
356 /// \brief Clears the union-find data structure
358 /// Erase each item from the data structure.
365 /// \brief Finds the component of the given element.
367 /// The method returns the component id of the given element.
368 int find(const Item &item) const {
369 return ~(items[repIndex(index[item])].parent);
372 /// \brief Joining the component of element \e a and element \e b.
374 /// This is the \e union operation of the Union-Find structure.
375 /// Joins the component of element \e a and component of
376 /// element \e b. If \e a and \e b are in the same component then
377 /// returns -1 else returns the remaining class.
378 int join(const Item& a, const Item& b) {
380 int ak = repIndex(index[a]);
381 int bk = repIndex(index[b]);
387 int acx = ~(items[ak].parent);
388 int bcx = ~(items[bk].parent);
392 if (classes[acx].size > classes[bcx].size) {
393 classes[acx].size += classes[bcx].size;
394 items[bk].parent = ak;
398 classes[bcx].size += classes[acx].size;
399 items[ak].parent = bk;
408 /// \brief Returns the size of the class.
410 /// Returns the size of the class.
411 int size(int cls) const {
412 return classes[cls].size;
415 /// \brief Splits up the component.
417 /// Splitting the component into singleton components (component
419 void split(int cls) {
420 int fdx = classes[cls].firstItem;
421 int idx = items[fdx].next;
423 int next = items[idx].next;
427 int cdx = newClass();
428 items[idx].parent = ~cdx;
431 classes[cdx].size = 1;
432 classes[cdx].firstItem = idx;
437 items[idx].prev = idx;
438 items[idx].next = idx;
440 classes[~(items[idx].parent)].size = 1;
444 /// \brief Removes the given element from the structure.
446 /// Removes the element from its component and if the component becomes
447 /// empty then removes that component from the component list.
449 /// \warning It is an error to remove an element which is not in
451 /// \warning This running time of this operation is proportional to the
452 /// number of the items in this class.
453 void erase(const Item& item) {
454 int idx = index[item];
455 int fdx = items[idx].next;
457 int cdx = classIndex(idx);
460 items[idx].next = firstFreeItem;
464 classes[cdx].firstItem = fdx;
466 items[fdx].parent = ~cdx;
469 idx = items[fdx].next;
471 items[idx].parent = fdx;
472 idx = items[idx].next;
479 /// \brief Gives back a representant item of the component.
481 /// Gives back a representant item of the component.
482 Item item(int cls) const {
483 return items[classes[cls].firstItem].item;
486 /// \brief Removes the component of the given element from the structure.
488 /// Removes the component of the given element from the structure.
490 /// \warning It is an error to give an element which is not in the
492 void eraseClass(int cls) {
493 int fdx = classes[cls].firstItem;
495 items[items[fdx].prev].next = firstFreeItem;
499 /// \brief Lemon style iterator for the representant items.
501 /// ClassIt is a lemon style iterator for the components. It iterates
502 /// on the ids of the classes.
505 /// \brief Constructor of the iterator
507 /// Constructor of the iterator
508 ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
509 cdx = unionFind->firstClass;
512 /// \brief Constructor to get invalid iterator
514 /// Constructor to get invalid iterator
515 ClassIt(Invalid) : unionFind(0), cdx(-1) {}
517 /// \brief Increment operator
519 /// It steps to the next representant item.
520 ClassIt& operator++() {
521 cdx = unionFind->classes[cdx].next;
525 /// \brief Conversion operator
527 /// It converts the iterator to the current representant item.
528 operator int() const {
532 /// \brief Equality operator
534 /// Equality operator
535 bool operator==(const ClassIt& i) {
539 /// \brief Inequality operator
541 /// Inequality operator
542 bool operator!=(const ClassIt& i) {
547 const UnionFindEnum* unionFind;
551 /// \brief Lemon style iterator for the items of a component.
553 /// ClassIt is a lemon style iterator for the components. It iterates
554 /// on the items of a class. By example if you want to iterate on
555 /// each items of each classes then you may write the next code.
557 /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
558 /// std::cout << "Class: ";
559 /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
560 /// std::cout << toString(iit) << ' ' << std::endl;
562 /// std::cout << std::endl;
567 /// \brief Constructor of the iterator
569 /// Constructor of the iterator. The iterator iterates
570 /// on the class of the \c item.
571 ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
572 fdx = idx = unionFind->classes[cls].firstItem;
575 /// \brief Constructor to get invalid iterator
577 /// Constructor to get invalid iterator
578 ItemIt(Invalid) : unionFind(0), idx(-1) {}
580 /// \brief Increment operator
582 /// It steps to the next item in the class.
583 ItemIt& operator++() {
584 idx = unionFind->items[idx].next;
585 if (idx == fdx) idx = -1;
589 /// \brief Conversion operator
591 /// It converts the iterator to the current item.
592 operator const Item&() const {
593 return unionFind->items[idx].item;
596 /// \brief Equality operator
598 /// Equality operator
599 bool operator==(const ItemIt& i) {
603 /// \brief Inequality operator
605 /// Inequality operator
606 bool operator!=(const ItemIt& i) {
611 const UnionFindEnum* unionFind;
619 /// \brief A \e Extend-Find data structure implementation which
620 /// is able to enumerate the components.
622 /// The class implements an \e Extend-Find data structure which is
623 /// able to enumerate the components and the items in a
624 /// component. The data structure is a simplification of the
625 /// Union-Find structure, and it does not allow to merge two components.
627 /// \pre You need to add all the elements by the \ref insert()
629 template <typename _ItemIntMap>
630 class ExtendFindEnum {
633 typedef _ItemIntMap ItemIntMap;
634 typedef typename ItemIntMap::Key Item;
646 std::vector<ItemT> items;
654 std::vector<ClassT> classes;
656 int firstClass, firstFreeClass;
659 if (firstFreeClass != -1) {
660 int cdx = firstFreeClass;
661 firstFreeClass = classes[cdx].next;
664 classes.push_back(ClassT());
665 return classes.size() - 1;
670 if (firstFreeItem != -1) {
671 int idx = firstFreeItem;
672 firstFreeItem = items[idx].next;
675 items.push_back(ItemT());
676 return items.size() - 1;
682 /// \brief Constructor
683 ExtendFindEnum(ItemIntMap& _index)
684 : index(_index), items(), firstFreeItem(-1),
685 classes(), firstClass(-1), firstFreeClass(-1) {}
687 /// \brief Inserts the given element into a new component.
689 /// This method creates a new component consisting only of the
691 int insert(const Item& item) {
692 int cdx = newClass();
693 classes[cdx].prev = -1;
694 classes[cdx].next = firstClass;
698 items[idx].item = item;
699 items[idx].cls = cdx;
700 items[idx].prev = idx;
701 items[idx].next = idx;
703 classes[cdx].firstItem = idx;
705 index.set(item, idx);
710 /// \brief Inserts the given element into the given component.
712 /// This methods inserts the element \e item a into the \e cls class.
713 void insert(const Item& item, int cls) {
715 int rdx = classes[cls].firstItem;
716 items[idx].item = item;
717 items[idx].cls = cls;
719 items[idx].prev = rdx;
720 items[idx].next = items[rdx].next;
721 items[items[rdx].next].prev = idx;
722 items[rdx].next = idx;
724 index.set(item, idx);
727 /// \brief Clears the union-find data structure
729 /// Erase each item from the data structure.
733 firstClass = firstFreeClass = firstFreeItem = -1;
736 /// \brief Gives back the class of the \e item.
738 /// Gives back the class of the \e item.
739 int find(const Item &item) const {
740 return items[index[item]].cls;
743 /// \brief Gives back a representant item of the component.
745 /// Gives back a representant item of the component.
746 Item item(int cls) const {
747 return items[classes[cls].firstItem].item;
750 /// \brief Removes the given element from the structure.
752 /// Removes the element from its component and if the component becomes
753 /// empty then removes that component from the component list.
755 /// \warning It is an error to remove an element which is not in
757 void erase(const Item &item) {
758 int idx = index[item];
759 int cdx = items[idx].cls;
761 if (idx == items[idx].next) {
762 if (classes[cdx].prev != -1) {
763 classes[classes[cdx].prev].next = classes[cdx].next;
765 firstClass = classes[cdx].next;
767 if (classes[cdx].next != -1) {
768 classes[classes[cdx].next].prev = classes[cdx].prev;
770 classes[cdx].next = firstFreeClass;
771 firstFreeClass = cdx;
773 classes[cdx].firstItem = items[idx].next;
774 items[items[idx].next].prev = items[idx].prev;
775 items[items[idx].prev].next = items[idx].next;
777 items[idx].next = firstFreeItem;
783 /// \brief Removes the component of the given element from the structure.
785 /// Removes the component of the given element from the structure.
787 /// \warning It is an error to give an element which is not in the
789 void eraseClass(int cdx) {
790 int idx = classes[cdx].firstItem;
791 items[items[idx].prev].next = firstFreeItem;
794 if (classes[cdx].prev != -1) {
795 classes[classes[cdx].prev].next = classes[cdx].next;
797 firstClass = classes[cdx].next;
799 if (classes[cdx].next != -1) {
800 classes[classes[cdx].next].prev = classes[cdx].prev;
802 classes[cdx].next = firstFreeClass;
803 firstFreeClass = cdx;
806 /// \brief Lemon style iterator for the classes.
808 /// ClassIt is a lemon style iterator for the components. It iterates
809 /// on the ids of classes.
812 /// \brief Constructor of the iterator
814 /// Constructor of the iterator
815 ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
816 cdx = extendFind->firstClass;
819 /// \brief Constructor to get invalid iterator
821 /// Constructor to get invalid iterator
822 ClassIt(Invalid) : extendFind(0), cdx(-1) {}
824 /// \brief Increment operator
826 /// It steps to the next representant item.
827 ClassIt& operator++() {
828 cdx = extendFind->classes[cdx].next;
832 /// \brief Conversion operator
834 /// It converts the iterator to the current class id.
835 operator int() const {
839 /// \brief Equality operator
841 /// Equality operator
842 bool operator==(const ClassIt& i) {
846 /// \brief Inequality operator
848 /// Inequality operator
849 bool operator!=(const ClassIt& i) {
854 const ExtendFindEnum* extendFind;
858 /// \brief Lemon style iterator for the items of a component.
860 /// ClassIt is a lemon style iterator for the components. It iterates
861 /// on the items of a class. By example if you want to iterate on
862 /// each items of each classes then you may write the next code.
864 /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
865 /// std::cout << "Class: ";
866 /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
867 /// std::cout << toString(iit) << ' ' << std::endl;
869 /// std::cout << std::endl;
874 /// \brief Constructor of the iterator
876 /// Constructor of the iterator. The iterator iterates
877 /// on the class of the \c item.
878 ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
879 fdx = idx = extendFind->classes[cls].firstItem;
882 /// \brief Constructor to get invalid iterator
884 /// Constructor to get invalid iterator
885 ItemIt(Invalid) : extendFind(0), idx(-1) {}
887 /// \brief Increment operator
889 /// It steps to the next item in the class.
890 ItemIt& operator++() {
891 idx = extendFind->items[idx].next;
892 if (fdx == idx) idx = -1;
896 /// \brief Conversion operator
898 /// It converts the iterator to the current item.
899 operator const Item&() const {
900 return extendFind->items[idx].item;
903 /// \brief Equality operator
905 /// Equality operator
906 bool operator==(const ItemIt& i) {
910 /// \brief Inequality operator
912 /// Inequality operator
913 bool operator!=(const ItemIt& i) {
918 const ExtendFindEnum* extendFind;
928 #endif //LEMON_UNION_FIND_H