alpar@906
|
1 |
/* -*- C++ -*-
|
alpar@906
|
2 |
*
|
alpar@1956
|
3 |
* This file is a part of LEMON, a generic C++ optimization library
|
alpar@1956
|
4 |
*
|
alpar@1956
|
5 |
* Copyright (C) 2003-2006
|
alpar@1956
|
6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
alpar@1359
|
7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
alpar@906
|
8 |
*
|
alpar@906
|
9 |
* Permission to use, modify and distribute this software is granted
|
alpar@906
|
10 |
* provided that this copyright notice appears in all copies. For
|
alpar@906
|
11 |
* precise terms see the accompanying LICENSE file.
|
alpar@906
|
12 |
*
|
alpar@906
|
13 |
* This software is provided "AS IS" with no warranty of any kind,
|
alpar@906
|
14 |
* express or implied, and with no claim as to its suitability for any
|
alpar@906
|
15 |
* purpose.
|
alpar@906
|
16 |
*
|
alpar@906
|
17 |
*/
|
alpar@906
|
18 |
|
alpar@921
|
19 |
#ifndef LEMON_UNION_FIND_H
|
alpar@921
|
20 |
#define LEMON_UNION_FIND_H
|
beckerjc@483
|
21 |
|
klao@491
|
22 |
//!\ingroup auxdat
|
beckerjc@483
|
23 |
//!\file
|
beckerjc@483
|
24 |
//!\brief Union-Find data structures.
|
alpar@774
|
25 |
//!
|
beckerjc@483
|
26 |
|
beckerjc@483
|
27 |
#include <vector>
|
beckerjc@483
|
28 |
#include <list>
|
beckerjc@483
|
29 |
#include <utility>
|
beckerjc@483
|
30 |
#include <algorithm>
|
beckerjc@483
|
31 |
|
deba@1993
|
32 |
#include <lemon/bits/invalid.h>
|
beckerjc@483
|
33 |
|
alpar@921
|
34 |
namespace lemon {
|
beckerjc@483
|
35 |
|
beckerjc@483
|
36 |
//! \addtogroup auxdat
|
beckerjc@483
|
37 |
//! @{
|
beckerjc@483
|
38 |
|
deba@2205
|
39 |
/// \brief A \e Union-Find data structure implementation
|
deba@2205
|
40 |
///
|
deba@2205
|
41 |
/// The class implements the \e Union-Find data structure.
|
deba@2205
|
42 |
/// The union operation uses rank heuristic, while
|
deba@2205
|
43 |
/// the find operation uses path compression.
|
deba@2205
|
44 |
/// This is a very simple but efficient implementation, providing
|
deba@2205
|
45 |
/// only four methods: join (union), find, insert and size.
|
deba@2205
|
46 |
/// For more features see the \ref UnionFindEnum class.
|
deba@2205
|
47 |
///
|
deba@2205
|
48 |
/// It is primarily used in Kruskal algorithm for finding minimal
|
deba@2205
|
49 |
/// cost spanning tree in a graph.
|
deba@2205
|
50 |
/// \sa kruskal()
|
deba@2205
|
51 |
///
|
deba@2205
|
52 |
/// \pre You need to add all the elements by the \ref insert()
|
deba@2205
|
53 |
/// method.
|
deba@2205
|
54 |
template <typename Item, typename ItemIntMap>
|
beckerjc@483
|
55 |
class UnionFind {
|
beckerjc@483
|
56 |
|
beckerjc@483
|
57 |
public:
|
deba@2205
|
58 |
typedef Item ElementType;
|
beckerjc@483
|
59 |
|
beckerjc@483
|
60 |
private:
|
deba@2205
|
61 |
// If the items vector stores negative value for an item then
|
deba@2205
|
62 |
// that item is root item and it has -items[it] component size.
|
deba@2205
|
63 |
// Else the items[it] contains the index of the parent.
|
deba@2205
|
64 |
std::vector<int> items;
|
deba@2205
|
65 |
ItemIntMap& index;
|
deba@2205
|
66 |
|
deba@2205
|
67 |
bool rep(int idx) const {
|
deba@2205
|
68 |
return items[idx] < 0;
|
deba@2205
|
69 |
}
|
deba@2205
|
70 |
|
deba@2205
|
71 |
int repIndex(int idx) const {
|
deba@2205
|
72 |
int k = idx;
|
deba@2205
|
73 |
while (!rep(k)) {
|
deba@2205
|
74 |
k = items[k] ;
|
deba@2205
|
75 |
}
|
deba@2205
|
76 |
while (idx != k) {
|
deba@2205
|
77 |
int next = items[idx];
|
deba@2205
|
78 |
const_cast<int&>(items[idx]) = k;
|
deba@2205
|
79 |
idx = next;
|
deba@2205
|
80 |
}
|
deba@2205
|
81 |
return k;
|
deba@2205
|
82 |
}
|
beckerjc@483
|
83 |
|
beckerjc@483
|
84 |
public:
|
beckerjc@483
|
85 |
|
deba@2205
|
86 |
/// \brief Constructor
|
deba@2205
|
87 |
///
|
deba@2205
|
88 |
/// Constructor of the UnionFind class. You should give an item to
|
deba@2205
|
89 |
/// integer map which will be used from the data structure. If you
|
deba@2205
|
90 |
/// modify directly this map that may cause segmentation fault,
|
deba@2205
|
91 |
/// invalid data structure, or infinite loop when you use again
|
deba@2205
|
92 |
/// the union-find.
|
deba@2205
|
93 |
UnionFind(ItemIntMap& m) : index(m) {}
|
beckerjc@483
|
94 |
|
deba@2205
|
95 |
/// \brief Returns the index of the element's component.
|
deba@2205
|
96 |
///
|
deba@2205
|
97 |
/// The method returns the index of the element's component.
|
deba@2205
|
98 |
/// This is an integer between zero and the number of inserted elements.
|
deba@2205
|
99 |
///
|
deba@2205
|
100 |
int find(const Item& a) {
|
deba@2205
|
101 |
return repIndex(index[a]);
|
beckerjc@483
|
102 |
}
|
beckerjc@483
|
103 |
|
deba@2205
|
104 |
/// \brief Inserts a new element into the structure.
|
deba@2205
|
105 |
///
|
deba@2205
|
106 |
/// This method inserts a new element into the data structure.
|
deba@2205
|
107 |
///
|
deba@2205
|
108 |
/// The method returns the index of the new component.
|
deba@2205
|
109 |
int insert(const Item& a) {
|
deba@2205
|
110 |
int n = items.size();
|
deba@2205
|
111 |
items.push_back(-1);
|
deba@2205
|
112 |
index.set(a,n);
|
beckerjc@483
|
113 |
return n;
|
beckerjc@483
|
114 |
}
|
beckerjc@483
|
115 |
|
deba@2205
|
116 |
/// \brief Joining the components of element \e a and element \e b.
|
deba@2205
|
117 |
///
|
deba@2205
|
118 |
/// This is the \e union operation of the Union-Find structure.
|
deba@2205
|
119 |
/// Joins the component of element \e a and component of
|
deba@2205
|
120 |
/// element \e b. If \e a and \e b are in the same component then
|
deba@2205
|
121 |
/// it returns false otherwise it returns true.
|
deba@2205
|
122 |
bool join(const Item& a, const Item& b) {
|
deba@2205
|
123 |
int ka = repIndex(index[a]);
|
deba@2205
|
124 |
int kb = repIndex(index[b]);
|
beckerjc@483
|
125 |
|
deba@2205
|
126 |
if ( ka == kb )
|
beckerjc@483
|
127 |
return false;
|
beckerjc@483
|
128 |
|
deba@2205
|
129 |
if (items[ka] < items[kb]) {
|
deba@2205
|
130 |
items[ka] += items[kb];
|
deba@2205
|
131 |
items[kb] = ka;
|
deba@2205
|
132 |
} else {
|
deba@2205
|
133 |
items[kb] += items[ka];
|
deba@2205
|
134 |
items[ka] = kb;
|
beckerjc@483
|
135 |
}
|
beckerjc@483
|
136 |
return true;
|
beckerjc@483
|
137 |
}
|
beckerjc@483
|
138 |
|
deba@2205
|
139 |
/// \brief Returns the size of the component of element \e a.
|
deba@2205
|
140 |
///
|
deba@2205
|
141 |
/// Returns the size of the component of element \e a.
|
deba@2205
|
142 |
int size(const Item& a) {
|
deba@2205
|
143 |
int k = repIndex(index[a]);
|
deba@2205
|
144 |
return - items[k];
|
beckerjc@483
|
145 |
}
|
beckerjc@483
|
146 |
|
beckerjc@483
|
147 |
};
|
beckerjc@483
|
148 |
|
beckerjc@483
|
149 |
|
deba@2205
|
150 |
/// \brief A \e Union-Find data structure implementation which
|
deba@2205
|
151 |
/// is able to enumerate the components.
|
deba@2205
|
152 |
///
|
deba@2205
|
153 |
/// The class implements a \e Union-Find data structure
|
deba@2205
|
154 |
/// which is able to enumerate the components and the items in
|
deba@2205
|
155 |
/// a component. If you don't need this feature then perhaps it's
|
deba@2205
|
156 |
/// better to use the \ref UnionFind class which is more efficient.
|
deba@2205
|
157 |
///
|
deba@2205
|
158 |
/// The union operation uses rank heuristic, while
|
deba@2205
|
159 |
/// the find operation uses path compression.
|
deba@2205
|
160 |
///
|
deba@2205
|
161 |
/// \pre You need to add all the elements by the \ref insert()
|
deba@2205
|
162 |
/// method.
|
deba@2205
|
163 |
///
|
deba@2205
|
164 |
template <typename _Item, typename _ItemIntMap>
|
deba@2205
|
165 |
class UnionFindEnum {
|
deba@2205
|
166 |
public:
|
deba@2205
|
167 |
|
deba@2205
|
168 |
typedef _Item Item;
|
deba@2205
|
169 |
typedef _ItemIntMap ItemIntMap;
|
deba@2205
|
170 |
|
deba@2205
|
171 |
private:
|
deba@2205
|
172 |
|
deba@2205
|
173 |
// If the parent stores negative value for an item then that item
|
deba@2205
|
174 |
// is root item and it has -items[it].parent component size. Else
|
deba@2205
|
175 |
// the items[it].parent contains the index of the parent.
|
deba@2205
|
176 |
//
|
deba@2205
|
177 |
// The \c nextItem and \c prevItem provides the double-linked
|
deba@2205
|
178 |
// cyclic list of one component's items. The \c prevClass and
|
deba@2205
|
179 |
// \c nextClass gives the double linked list of the representant
|
deba@2205
|
180 |
// items.
|
deba@2205
|
181 |
struct ItemT {
|
deba@2205
|
182 |
int parent;
|
deba@2205
|
183 |
Item item;
|
beckerjc@483
|
184 |
|
deba@2205
|
185 |
int nextItem, prevItem;
|
deba@2205
|
186 |
int nextClass, prevClass;
|
deba@2205
|
187 |
};
|
beckerjc@483
|
188 |
|
deba@2205
|
189 |
std::vector<ItemT> items;
|
deba@2205
|
190 |
ItemIntMap& index;
|
beckerjc@483
|
191 |
|
deba@2205
|
192 |
int firstClass;
|
beckerjc@483
|
193 |
|
beckerjc@483
|
194 |
|
deba@2205
|
195 |
bool rep(int idx) const {
|
deba@2205
|
196 |
return items[idx].parent < 0;
|
beckerjc@483
|
197 |
}
|
beckerjc@483
|
198 |
|
deba@2205
|
199 |
int repIndex(int idx) const {
|
deba@2205
|
200 |
int k = idx;
|
deba@2205
|
201 |
while (!rep(k)) {
|
deba@2205
|
202 |
k = items[k].parent;
|
deba@2205
|
203 |
}
|
deba@2205
|
204 |
while (idx != k) {
|
deba@2205
|
205 |
int next = items[idx].parent;
|
deba@2205
|
206 |
const_cast<int&>(items[idx].parent) = k;
|
deba@2205
|
207 |
idx = next;
|
deba@2205
|
208 |
}
|
deba@2205
|
209 |
return k;
|
deba@2205
|
210 |
}
|
deba@2205
|
211 |
|
deba@2205
|
212 |
void unlaceClass(int k) {
|
deba@2205
|
213 |
if (items[k].prevClass != -1) {
|
deba@2205
|
214 |
items[items[k].prevClass].nextClass = items[k].nextClass;
|
deba@2205
|
215 |
} else {
|
deba@2205
|
216 |
firstClass = items[k].nextClass;
|
deba@2205
|
217 |
}
|
deba@2205
|
218 |
if (items[k].nextClass != -1) {
|
deba@2205
|
219 |
items[items[k].nextClass].prevClass = items[k].prevClass;
|
deba@2205
|
220 |
}
|
deba@2205
|
221 |
}
|
deba@2205
|
222 |
|
deba@2205
|
223 |
void spliceItems(int ak, int bk) {
|
deba@2205
|
224 |
items[items[ak].prevItem].nextItem = bk;
|
deba@2205
|
225 |
items[items[bk].prevItem].nextItem = ak;
|
deba@2205
|
226 |
int tmp = items[ak].prevItem;
|
deba@2205
|
227 |
items[ak].prevItem = items[bk].prevItem;
|
deba@2205
|
228 |
items[bk].prevItem = tmp;
|
deba@2205
|
229 |
|
klao@2003
|
230 |
}
|
klao@2003
|
231 |
|
beckerjc@483
|
232 |
public:
|
beckerjc@483
|
233 |
|
deba@2205
|
234 |
UnionFindEnum(ItemIntMap& _index)
|
deba@2205
|
235 |
: items(), index(_index), firstClass(-1) {}
|
deba@2205
|
236 |
|
deba@2205
|
237 |
/// \brief Inserts the given element into a new component.
|
deba@2205
|
238 |
///
|
deba@2205
|
239 |
/// This method creates a new component consisting only of the
|
deba@2205
|
240 |
/// given element.
|
deba@2205
|
241 |
///
|
deba@2205
|
242 |
void insert(const Item& item) {
|
deba@2205
|
243 |
ItemT t;
|
beckerjc@483
|
244 |
|
deba@2205
|
245 |
int idx = items.size();
|
deba@2205
|
246 |
index.set(item, idx);
|
beckerjc@483
|
247 |
|
deba@2205
|
248 |
t.nextItem = idx;
|
deba@2205
|
249 |
t.prevItem = idx;
|
deba@2205
|
250 |
t.item = item;
|
deba@2205
|
251 |
t.parent = -1;
|
deba@2205
|
252 |
|
deba@2205
|
253 |
t.nextClass = firstClass;
|
deba@2205
|
254 |
if (firstClass != -1) {
|
deba@2205
|
255 |
items[firstClass].prevClass = idx;
|
deba@2205
|
256 |
}
|
deba@2205
|
257 |
t.prevClass = -1;
|
deba@2205
|
258 |
firstClass = idx;
|
beckerjc@483
|
259 |
|
deba@2205
|
260 |
items.push_back(t);
|
beckerjc@483
|
261 |
}
|
beckerjc@483
|
262 |
|
deba@2205
|
263 |
/// \brief Inserts the given element into the component of the others.
|
deba@2205
|
264 |
///
|
deba@2205
|
265 |
/// This methods inserts the element \e a into the component of the
|
deba@2205
|
266 |
/// element \e comp.
|
deba@2205
|
267 |
void insert(const Item& item, const Item& comp) {
|
deba@2205
|
268 |
int k = repIndex(index[comp]);
|
deba@2205
|
269 |
ItemT t;
|
beckerjc@483
|
270 |
|
deba@2205
|
271 |
int idx = items.size();
|
deba@2205
|
272 |
index.set(item, idx);
|
deba@2205
|
273 |
|
deba@2205
|
274 |
t.prevItem = k;
|
deba@2205
|
275 |
t.nextItem = items[k].nextItem;
|
deba@2205
|
276 |
items[items[k].nextItem].prevItem = idx;
|
deba@2205
|
277 |
items[k].nextItem = idx;
|
deba@2205
|
278 |
|
deba@2205
|
279 |
t.item = item;
|
deba@2205
|
280 |
t.parent = k;
|
deba@2205
|
281 |
|
deba@2205
|
282 |
--items[k].parent;
|
deba@2205
|
283 |
|
deba@2205
|
284 |
items.push_back(t);
|
beckerjc@483
|
285 |
}
|
beckerjc@483
|
286 |
|
deba@2205
|
287 |
/// \brief Finds the leader of the component of the given element.
|
deba@2205
|
288 |
///
|
deba@2205
|
289 |
/// The method returns the leader of the component of the given element.
|
deba@2205
|
290 |
const Item& find(const Item &item) const {
|
deba@2205
|
291 |
return items[repIndex(index[item])].item;
|
beckerjc@483
|
292 |
}
|
beckerjc@483
|
293 |
|
deba@2205
|
294 |
/// \brief Joining the component of element \e a and element \e b.
|
deba@2205
|
295 |
///
|
deba@2205
|
296 |
/// This is the \e union operation of the Union-Find structure.
|
deba@2205
|
297 |
/// Joins the component of element \e a and component of
|
deba@2205
|
298 |
/// element \e b. If \e a and \e b are in the same component then
|
deba@2205
|
299 |
/// returns false else returns true.
|
deba@2205
|
300 |
bool join(const Item& a, const Item& b) {
|
beckerjc@483
|
301 |
|
deba@2205
|
302 |
int ak = repIndex(index[a]);
|
deba@2205
|
303 |
int bk = repIndex(index[b]);
|
beckerjc@483
|
304 |
|
deba@2205
|
305 |
if (ak == bk) {
|
beckerjc@483
|
306 |
return false;
|
beckerjc@483
|
307 |
}
|
beckerjc@483
|
308 |
|
deba@2205
|
309 |
if ( items[ak].parent < items[bk].parent ) {
|
deba@2205
|
310 |
unlaceClass(bk);
|
deba@2205
|
311 |
items[ak].parent += items[bk].parent;
|
deba@2205
|
312 |
items[bk].parent = ak;
|
deba@2205
|
313 |
} else {
|
deba@2205
|
314 |
unlaceClass(bk);
|
deba@2205
|
315 |
items[bk].parent += items[ak].parent;
|
deba@2205
|
316 |
items[ak].parent = bk;
|
beckerjc@483
|
317 |
}
|
deba@2205
|
318 |
spliceItems(ak, bk);
|
beckerjc@483
|
319 |
|
beckerjc@483
|
320 |
return true;
|
beckerjc@483
|
321 |
}
|
beckerjc@483
|
322 |
|
deba@2205
|
323 |
/// \brief Returns the size of the component of element \e a.
|
deba@2205
|
324 |
///
|
deba@2205
|
325 |
/// Returns the size of the component of element \e a.
|
deba@2205
|
326 |
int size(const Item &item) const {
|
deba@2205
|
327 |
return - items[repIndex(index[item])].parent;
|
beckerjc@483
|
328 |
}
|
beckerjc@483
|
329 |
|
deba@2205
|
330 |
/// \brief Splits up the component of the element.
|
deba@2205
|
331 |
///
|
deba@2205
|
332 |
/// Splitting the component of the element into sigleton
|
deba@2205
|
333 |
/// components (component of size one).
|
deba@2205
|
334 |
void split(const Item &item) {
|
deba@2205
|
335 |
int k = repIndex(index[item]);
|
deba@2205
|
336 |
int idx = items[k].nextItem;
|
deba@2205
|
337 |
while (idx != k) {
|
deba@2205
|
338 |
int next = items[idx].nextItem;
|
deba@2205
|
339 |
|
deba@2205
|
340 |
items[idx].parent = -1;
|
deba@2205
|
341 |
items[idx].prevItem = idx;
|
deba@2205
|
342 |
items[idx].nextItem = idx;
|
deba@2205
|
343 |
|
deba@2205
|
344 |
items[idx].nextClass = firstClass;
|
deba@2205
|
345 |
items[firstClass].prevClass = idx;
|
deba@2205
|
346 |
firstClass = idx;
|
beckerjc@483
|
347 |
|
deba@2205
|
348 |
idx = next;
|
beckerjc@483
|
349 |
}
|
beckerjc@483
|
350 |
|
deba@2205
|
351 |
items[idx].parent = -1;
|
deba@2205
|
352 |
items[idx].prevItem = idx;
|
deba@2205
|
353 |
items[idx].nextItem = idx;
|
deba@2205
|
354 |
|
deba@2205
|
355 |
items[firstClass].prevClass = -1;
|
beckerjc@483
|
356 |
}
|
beckerjc@483
|
357 |
|
deba@2205
|
358 |
/// \brief Sets the given element to the leader element of its component.
|
deba@2205
|
359 |
///
|
deba@2205
|
360 |
/// Sets the given element to the leader element of its component.
|
deba@2205
|
361 |
void makeRep(const Item &item) {
|
deba@2205
|
362 |
int nk = index[item];
|
deba@2205
|
363 |
int k = repIndex(nk);
|
deba@2205
|
364 |
if (nk == k) return;
|
deba@2205
|
365 |
|
deba@2205
|
366 |
if (items[k].prevClass != -1) {
|
deba@2205
|
367 |
items[items[k].prevClass].nextClass = nk;
|
deba@2205
|
368 |
} else {
|
deba@2205
|
369 |
firstClass = nk;
|
deba@2205
|
370 |
}
|
deba@2205
|
371 |
if (items[k].nextClass != -1) {
|
deba@2205
|
372 |
items[items[k].nextClass].prevClass = nk;
|
deba@2205
|
373 |
}
|
deba@2205
|
374 |
|
deba@2205
|
375 |
int idx = items[k].nextItem;
|
deba@2205
|
376 |
while (idx != k) {
|
deba@2205
|
377 |
items[idx].parent = nk;
|
deba@2205
|
378 |
idx = items[idx].nextItem;
|
deba@2205
|
379 |
}
|
deba@2205
|
380 |
|
deba@2205
|
381 |
items[nk].parent = items[k].parent;
|
deba@2205
|
382 |
items[k].parent = nk;
|
beckerjc@483
|
383 |
}
|
beckerjc@483
|
384 |
|
deba@2205
|
385 |
/// \brief Removes the given element from the structure.
|
deba@2205
|
386 |
///
|
deba@2205
|
387 |
/// Removes the element from its component and if the component becomes
|
deba@2205
|
388 |
/// empty then removes that component from the component list.
|
deba@2205
|
389 |
///
|
deba@2205
|
390 |
/// \warning It is an error to remove an element which is not in
|
deba@2205
|
391 |
/// the structure.
|
deba@2205
|
392 |
void erase(const Item &item) {
|
deba@2205
|
393 |
int idx = index[item];
|
deba@2205
|
394 |
if (rep(idx)) {
|
deba@2205
|
395 |
int k = idx;
|
deba@2205
|
396 |
if (items[k].parent == -1) {
|
deba@2205
|
397 |
unlaceClass(idx);
|
deba@2205
|
398 |
return;
|
deba@2205
|
399 |
} else {
|
deba@2205
|
400 |
int nk = items[k].nextItem;
|
deba@2205
|
401 |
if (items[k].prevClass != -1) {
|
deba@2205
|
402 |
items[items[k].prevClass].nextClass = nk;
|
deba@2205
|
403 |
} else {
|
deba@2205
|
404 |
firstClass = nk;
|
deba@2205
|
405 |
}
|
deba@2205
|
406 |
if (items[k].nextClass != -1) {
|
deba@2205
|
407 |
items[items[k].nextClass].prevClass = nk;
|
deba@2205
|
408 |
}
|
deba@2205
|
409 |
|
deba@2205
|
410 |
int idx = items[k].nextItem;
|
deba@2205
|
411 |
while (idx != k) {
|
deba@2205
|
412 |
items[idx].parent = nk;
|
deba@2205
|
413 |
idx = items[idx].nextItem;
|
deba@2205
|
414 |
}
|
deba@2205
|
415 |
|
deba@2205
|
416 |
items[nk].parent = items[k].parent + 1;
|
deba@2205
|
417 |
}
|
deba@2205
|
418 |
} else {
|
deba@2205
|
419 |
|
deba@2205
|
420 |
int k = repIndex(idx);
|
deba@2205
|
421 |
idx = items[k].nextItem;
|
deba@2205
|
422 |
while (idx != k) {
|
deba@2205
|
423 |
items[idx].parent = k;
|
deba@2205
|
424 |
idx = items[idx].nextItem;
|
deba@2205
|
425 |
}
|
beckerjc@483
|
426 |
|
deba@2205
|
427 |
++items[k].parent;
|
beckerjc@483
|
428 |
}
|
beckerjc@483
|
429 |
|
deba@2205
|
430 |
idx = index[item];
|
deba@2205
|
431 |
items[items[idx].prevItem].nextItem = items[idx].nextItem;
|
deba@2205
|
432 |
items[items[idx].nextItem].prevItem = items[idx].prevItem;
|
beckerjc@483
|
433 |
|
deba@2205
|
434 |
}
|
beckerjc@483
|
435 |
|
deba@2205
|
436 |
/// \brief Moves the given element to another component.
|
deba@2205
|
437 |
///
|
deba@2205
|
438 |
/// This method moves the element \e a from its component
|
deba@2205
|
439 |
/// to the component of \e comp.
|
deba@2205
|
440 |
/// If \e a and \e comp are in the same component then
|
deba@2205
|
441 |
/// it returns false otherwise it returns true.
|
deba@2205
|
442 |
bool move(const Item &item, const Item &comp) {
|
deba@2205
|
443 |
if (repIndex(index[item]) == repIndex(index[comp])) return false;
|
deba@2205
|
444 |
erase(item);
|
deba@2205
|
445 |
insert(item, comp);
|
beckerjc@483
|
446 |
return true;
|
beckerjc@483
|
447 |
}
|
beckerjc@483
|
448 |
|
beckerjc@483
|
449 |
|
deba@2205
|
450 |
/// \brief Removes the component of the given element from the structure.
|
deba@2205
|
451 |
///
|
deba@2205
|
452 |
/// Removes the component of the given element from the structure.
|
deba@2205
|
453 |
///
|
deba@2205
|
454 |
/// \warning It is an error to give an element which is not in the
|
deba@2205
|
455 |
/// structure.
|
deba@2205
|
456 |
void eraseClass(const Item &item) {
|
deba@2205
|
457 |
unlaceClass(repIndex(index[item]));
|
deba@2205
|
458 |
}
|
beckerjc@483
|
459 |
|
deba@2205
|
460 |
/// \brief Lemon style iterator for the representant items.
|
deba@2205
|
461 |
///
|
deba@2205
|
462 |
/// ClassIt is a lemon style iterator for the components. It iterates
|
deba@2205
|
463 |
/// on the representant items of the classes.
|
deba@2205
|
464 |
class ClassIt {
|
deba@2205
|
465 |
public:
|
deba@2205
|
466 |
/// \brief Constructor of the iterator
|
deba@2205
|
467 |
///
|
deba@2205
|
468 |
/// Constructor of the iterator
|
deba@2205
|
469 |
ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
|
deba@2205
|
470 |
idx = unionFind->firstClass;
|
beckerjc@483
|
471 |
}
|
beckerjc@483
|
472 |
|
deba@2205
|
473 |
/// \brief Constructor to get invalid iterator
|
deba@2205
|
474 |
///
|
deba@2205
|
475 |
/// Constructor to get invalid iterator
|
deba@2205
|
476 |
ClassIt(Invalid) : unionFind(0), idx(-1) {}
|
deba@2205
|
477 |
|
deba@2205
|
478 |
/// \brief Increment operator
|
deba@2205
|
479 |
///
|
deba@2205
|
480 |
/// It steps to the next representant item.
|
deba@2205
|
481 |
ClassIt& operator++() {
|
deba@2205
|
482 |
idx = unionFind->items[idx].nextClass;
|
deba@2205
|
483 |
return *this;
|
deba@2205
|
484 |
}
|
deba@2205
|
485 |
|
deba@2205
|
486 |
/// \brief Conversion operator
|
deba@2205
|
487 |
///
|
deba@2205
|
488 |
/// It converts the iterator to the current representant item.
|
deba@2205
|
489 |
operator const Item&() const {
|
deba@2205
|
490 |
return unionFind->items[idx].item;
|
beckerjc@483
|
491 |
}
|
beckerjc@483
|
492 |
|
deba@2205
|
493 |
/// \brief Equality operator
|
deba@2205
|
494 |
///
|
deba@2205
|
495 |
/// Equality operator
|
deba@2205
|
496 |
bool operator==(const ClassIt& i) {
|
deba@2205
|
497 |
return i.idx == idx;
|
deba@2205
|
498 |
}
|
beckerjc@483
|
499 |
|
deba@2205
|
500 |
/// \brief Inequality operator
|
deba@2205
|
501 |
///
|
deba@2205
|
502 |
/// Inequality operator
|
deba@2205
|
503 |
bool operator!=(const ClassIt& i) {
|
deba@2205
|
504 |
return i.idx != idx;
|
klao@2003
|
505 |
}
|
beckerjc@483
|
506 |
|
deba@2205
|
507 |
private:
|
deba@2205
|
508 |
const UnionFindEnum* unionFind;
|
deba@2205
|
509 |
int idx;
|
deba@2205
|
510 |
};
|
deba@2205
|
511 |
|
deba@2205
|
512 |
/// \brief Lemon style iterator for the items of a component.
|
deba@2205
|
513 |
///
|
deba@2205
|
514 |
/// ClassIt is a lemon style iterator for the components. It iterates
|
deba@2205
|
515 |
/// on the items of a class. By example if you want to iterate on
|
deba@2205
|
516 |
/// each items of each classes then you may write the next code.
|
deba@2205
|
517 |
///\code
|
deba@2205
|
518 |
/// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
|
deba@2205
|
519 |
/// std::cout << "Class: ";
|
deba@2205
|
520 |
/// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
|
deba@2205
|
521 |
/// std::cout << toString(iit) << ' ' << std::endl;
|
deba@2205
|
522 |
/// }
|
deba@2205
|
523 |
/// std::cout << std::endl;
|
deba@2205
|
524 |
/// }
|
deba@2205
|
525 |
///\endcode
|
deba@2205
|
526 |
class ItemIt {
|
deba@2205
|
527 |
public:
|
deba@2205
|
528 |
/// \brief Constructor of the iterator
|
deba@2205
|
529 |
///
|
deba@2205
|
530 |
/// Constructor of the iterator. The iterator iterates
|
deba@2205
|
531 |
/// on the class of the \c item.
|
deba@2205
|
532 |
ItemIt(const UnionFindEnum& ufe, const Item& item) : unionFind(&ufe) {
|
deba@2205
|
533 |
idx = unionFind->repIndex(unionFind->index[item]);
|
beckerjc@483
|
534 |
}
|
beckerjc@483
|
535 |
|
deba@2205
|
536 |
/// \brief Constructor to get invalid iterator
|
deba@2205
|
537 |
///
|
deba@2205
|
538 |
/// Constructor to get invalid iterator
|
deba@2205
|
539 |
ItemIt(Invalid) : unionFind(0), idx(-1) {}
|
deba@2205
|
540 |
|
deba@2205
|
541 |
/// \brief Increment operator
|
deba@2205
|
542 |
///
|
deba@2205
|
543 |
/// It steps to the next item in the class.
|
deba@2205
|
544 |
ItemIt& operator++() {
|
deba@2205
|
545 |
idx = unionFind->items[idx].nextItem;
|
deba@2205
|
546 |
if (unionFind->rep(idx)) idx = -1;
|
deba@2205
|
547 |
return *this;
|
klao@2003
|
548 |
}
|
deba@2205
|
549 |
|
deba@2205
|
550 |
/// \brief Conversion operator
|
deba@2205
|
551 |
///
|
deba@2205
|
552 |
/// It converts the iterator to the current item.
|
deba@2205
|
553 |
operator const Item&() const {
|
deba@2205
|
554 |
return unionFind->items[idx].item;
|
klao@2003
|
555 |
}
|
klao@2003
|
556 |
|
deba@2205
|
557 |
/// \brief Equality operator
|
deba@2205
|
558 |
///
|
deba@2205
|
559 |
/// Equality operator
|
deba@2205
|
560 |
bool operator==(const ItemIt& i) {
|
deba@2205
|
561 |
return i.idx == idx;
|
klao@2003
|
562 |
}
|
klao@2003
|
563 |
|
deba@2205
|
564 |
/// \brief Inequality operator
|
deba@2205
|
565 |
///
|
deba@2205
|
566 |
/// Inequality operator
|
deba@2205
|
567 |
bool operator!=(const ItemIt& i) {
|
deba@2205
|
568 |
return i.idx != idx;
|
deba@2205
|
569 |
}
|
deba@2205
|
570 |
|
deba@2205
|
571 |
private:
|
deba@2205
|
572 |
const UnionFindEnum* unionFind;
|
deba@2205
|
573 |
int idx;
|
beckerjc@483
|
574 |
};
|
beckerjc@483
|
575 |
|
beckerjc@483
|
576 |
};
|
beckerjc@483
|
577 |
|
beckerjc@483
|
578 |
|
beckerjc@483
|
579 |
//! @}
|
beckerjc@483
|
580 |
|
alpar@921
|
581 |
} //namespace lemon
|
beckerjc@483
|
582 |
|
alpar@921
|
583 |
#endif //LEMON_UNION_FIND_H
|