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;
181 // If the parent stores negative value for an item then that item
182 // is root item and it has -items[it].parent component size. Else
183 // the items[it].parent contains the index of the parent.
185 // The \c nextItem and \c prevItem provides the double-linked
186 // cyclic list of one component's items. The \c prevClass and
187 // \c nextClass gives the double linked list of the representant
193 int nextItem, prevItem;
194 int nextClass, prevClass;
197 std::vector<ItemT> items;
203 bool rep(int idx) const {
204 return items[idx].parent < 0;
207 int repIndex(int idx) const {
213 int next = items[idx].parent;
214 const_cast<int&>(items[idx].parent) = k;
220 void unlaceClass(int k) {
221 if (items[k].prevClass != -1) {
222 items[items[k].prevClass].nextClass = items[k].nextClass;
224 firstClass = items[k].nextClass;
226 if (items[k].nextClass != -1) {
227 items[items[k].nextClass].prevClass = items[k].prevClass;
231 void spliceItems(int ak, int bk) {
232 items[items[ak].prevItem].nextItem = bk;
233 items[items[bk].prevItem].nextItem = ak;
234 int tmp = items[ak].prevItem;
235 items[ak].prevItem = items[bk].prevItem;
236 items[bk].prevItem = tmp;
242 UnionFindEnum(ItemIntMap& _index)
243 : items(), index(_index), firstClass(-1) {}
245 /// \brief Inserts the given element into a new component.
247 /// This method creates a new component consisting only of the
250 void insert(const Item& item) {
253 int idx = items.size();
254 index.set(item, idx);
261 t.nextClass = firstClass;
262 if (firstClass != -1) {
263 items[firstClass].prevClass = idx;
271 /// \brief Inserts the given element into the component of the others.
273 /// This methods inserts the element \e a into the component of the
275 void insert(const Item& item, const Item& comp) {
276 int k = repIndex(index[comp]);
279 int idx = items.size();
280 index.set(item, idx);
283 t.nextItem = items[k].nextItem;
284 items[items[k].nextItem].prevItem = idx;
285 items[k].nextItem = idx;
295 /// \brief Clears the union-find data structure
297 /// Erase each item from the data structure.
303 /// \brief Finds the leader of the component of the given element.
305 /// The method returns the leader of the component of the given element.
306 const Item& find(const Item &item) const {
307 return items[repIndex(index[item])].item;
310 /// \brief Joining the component of element \e a and element \e b.
312 /// This is the \e union operation of the Union-Find structure.
313 /// Joins the component of element \e a and component of
314 /// element \e b. If \e a and \e b are in the same component then
315 /// returns false else returns true.
316 bool join(const Item& a, const Item& b) {
318 int ak = repIndex(index[a]);
319 int bk = repIndex(index[b]);
325 if ( items[ak].parent < items[bk].parent ) {
327 items[ak].parent += items[bk].parent;
328 items[bk].parent = ak;
331 items[bk].parent += items[ak].parent;
332 items[ak].parent = bk;
339 /// \brief Returns the size of the component of element \e a.
341 /// Returns the size of the component of element \e a.
342 int size(const Item &item) const {
343 return - items[repIndex(index[item])].parent;
346 /// \brief Splits up the component of the element.
348 /// Splitting the component of the element into sigleton
349 /// components (component of size one).
350 void split(const Item &item) {
351 int k = repIndex(index[item]);
352 int idx = items[k].nextItem;
354 int next = items[idx].nextItem;
356 items[idx].parent = -1;
357 items[idx].prevItem = idx;
358 items[idx].nextItem = idx;
360 items[idx].nextClass = firstClass;
361 items[firstClass].prevClass = idx;
367 items[idx].parent = -1;
368 items[idx].prevItem = idx;
369 items[idx].nextItem = idx;
371 items[firstClass].prevClass = -1;
374 /// \brief Sets the given element to the leader element of its component.
376 /// Sets the given element to the leader element of its component.
377 void makeRep(const Item &item) {
378 int nk = index[item];
379 int k = repIndex(nk);
382 if (items[k].prevClass != -1) {
383 items[items[k].prevClass].nextClass = nk;
387 if (items[k].nextClass != -1) {
388 items[items[k].nextClass].prevClass = nk;
391 int idx = items[k].nextItem;
393 items[idx].parent = nk;
394 idx = items[idx].nextItem;
397 items[nk].parent = items[k].parent;
398 items[k].parent = nk;
401 /// \brief Removes the given element from the structure.
403 /// Removes the element from its component and if the component becomes
404 /// empty then removes that component from the component list.
406 /// \warning It is an error to remove an element which is not in
408 void erase(const Item &item) {
409 int idx = index[item];
412 if (items[k].parent == -1) {
416 int nk = items[k].nextItem;
417 if (items[k].prevClass != -1) {
418 items[items[k].prevClass].nextClass = nk;
422 if (items[k].nextClass != -1) {
423 items[items[k].nextClass].prevClass = nk;
426 int l = items[k].nextItem;
428 items[l].parent = nk;
429 l = items[l].nextItem;
432 items[nk].parent = items[k].parent + 1;
436 int k = repIndex(idx);
437 idx = items[k].nextItem;
439 items[idx].parent = k;
440 idx = items[idx].nextItem;
447 items[items[idx].prevItem].nextItem = items[idx].nextItem;
448 items[items[idx].nextItem].prevItem = items[idx].prevItem;
452 /// \brief Moves the given element to another component.
454 /// This method moves the element \e a from its component
455 /// to the component of \e comp.
456 /// If \e a and \e comp are in the same component then
457 /// it returns false otherwise it returns true.
458 bool move(const Item &item, const Item &comp) {
459 if (repIndex(index[item]) == repIndex(index[comp])) return false;
466 /// \brief Removes the component of the given element from the structure.
468 /// Removes the component of the given element from the structure.
470 /// \warning It is an error to give an element which is not in the
472 void eraseClass(const Item &item) {
473 unlaceClass(repIndex(index[item]));
476 /// \brief Lemon style iterator for the representant items.
478 /// ClassIt is a lemon style iterator for the components. It iterates
479 /// on the representant items of the classes.
482 /// \brief Constructor of the iterator
484 /// Constructor of the iterator
485 ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
486 idx = unionFind->firstClass;
489 /// \brief Constructor to get invalid iterator
491 /// Constructor to get invalid iterator
492 ClassIt(Invalid) : unionFind(0), idx(-1) {}
494 /// \brief Increment operator
496 /// It steps to the next representant item.
497 ClassIt& operator++() {
498 idx = unionFind->items[idx].nextClass;
502 /// \brief Conversion operator
504 /// It converts the iterator to the current representant item.
505 operator const Item&() const {
506 return unionFind->items[idx].item;
509 /// \brief Equality operator
511 /// Equality operator
512 bool operator==(const ClassIt& i) {
516 /// \brief Inequality operator
518 /// Inequality operator
519 bool operator!=(const ClassIt& i) {
524 const UnionFindEnum* unionFind;
528 /// \brief Lemon style iterator for the items of a component.
530 /// ClassIt is a lemon style iterator for the components. It iterates
531 /// on the items of a class. By example if you want to iterate on
532 /// each items of each classes then you may write the next code.
534 /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
535 /// std::cout << "Class: ";
536 /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
537 /// std::cout << toString(iit) << ' ' << std::endl;
539 /// std::cout << std::endl;
544 /// \brief Constructor of the iterator
546 /// Constructor of the iterator. The iterator iterates
547 /// on the class of the \c item.
548 ItemIt(const UnionFindEnum& ufe, const Item& item) : unionFind(&ufe) {
549 idx = unionFind->repIndex(unionFind->index[item]);
552 /// \brief Constructor to get invalid iterator
554 /// Constructor to get invalid iterator
555 ItemIt(Invalid) : unionFind(0), idx(-1) {}
557 /// \brief Increment operator
559 /// It steps to the next item in the class.
560 ItemIt& operator++() {
561 idx = unionFind->items[idx].nextItem;
562 if (unionFind->rep(idx)) idx = -1;
566 /// \brief Conversion operator
568 /// It converts the iterator to the current item.
569 operator const Item&() const {
570 return unionFind->items[idx].item;
573 /// \brief Equality operator
575 /// Equality operator
576 bool operator==(const ItemIt& i) {
580 /// \brief Inequality operator
582 /// Inequality operator
583 bool operator!=(const ItemIt& i) {
588 const UnionFindEnum* unionFind;
599 #endif //LEMON_UNION_FIND_H