lemongraph 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (161) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +8 -0
  3. data/LICENSE +674 -0
  4. data/README.md +6 -0
  5. data/ext/lemon-1.3.1/AUTHORS +26 -0
  6. data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
  7. data/ext/lemon-1.3.1/INSTALL +167 -0
  8. data/ext/lemon-1.3.1/LICENSE +32 -0
  9. data/ext/lemon-1.3.1/NEWS +337 -0
  10. data/ext/lemon-1.3.1/README +50 -0
  11. data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
  12. data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
  13. data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
  14. data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
  15. data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
  16. data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
  17. data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
  18. data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
  19. data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
  20. data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
  21. data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
  22. data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
  23. data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
  24. data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
  25. data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
  26. data/ext/lemon-1.3.1/lemon/assert.h +214 -0
  27. data/ext/lemon-1.3.1/lemon/base.cc +37 -0
  28. data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
  29. data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
  30. data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
  31. data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
  32. data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
  33. data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
  34. data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
  35. data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
  36. data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
  37. data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
  38. data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
  39. data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
  40. data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
  41. data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
  42. data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
  43. data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
  44. data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
  45. data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
  46. data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
  47. data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
  48. data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
  49. data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
  50. data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
  51. data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
  52. data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
  53. data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
  54. data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
  55. data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
  56. data/ext/lemon-1.3.1/lemon/clp.h +164 -0
  57. data/ext/lemon-1.3.1/lemon/color.cc +44 -0
  58. data/ext/lemon-1.3.1/lemon/color.h +204 -0
  59. data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
  60. data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
  61. data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
  62. data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
  63. data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
  64. data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
  65. data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
  66. data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
  67. data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
  68. data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
  69. data/ext/lemon-1.3.1/lemon/core.h +2506 -0
  70. data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
  71. data/ext/lemon-1.3.1/lemon/counter.h +249 -0
  72. data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
  73. data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
  74. data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
  75. data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
  76. data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
  77. data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
  78. data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
  79. data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
  80. data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
  81. data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
  82. data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
  83. data/ext/lemon-1.3.1/lemon/error.h +276 -0
  84. data/ext/lemon-1.3.1/lemon/euler.h +287 -0
  85. data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
  86. data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
  87. data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
  88. data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
  89. data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
  90. data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
  91. data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
  92. data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
  93. data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
  94. data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
  95. data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
  96. data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
  97. data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
  98. data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
  99. data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
  100. data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
  101. data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
  102. data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
  103. data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
  104. data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
  105. data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
  106. data/ext/lemon-1.3.1/lemon/lp.h +95 -0
  107. data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
  108. data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
  109. data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
  110. data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
  111. data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
  112. data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
  113. data/ext/lemon-1.3.1/lemon/math.h +77 -0
  114. data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
  115. data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
  116. data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
  117. data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
  118. data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
  119. data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
  120. data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
  121. data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
  122. data/ext/lemon-1.3.1/lemon/path.h +1164 -0
  123. data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
  124. data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
  125. data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
  126. data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
  127. data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
  128. data/ext/lemon-1.3.1/lemon/random.cc +29 -0
  129. data/ext/lemon-1.3.1/lemon/random.h +1005 -0
  130. data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
  131. data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
  132. data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
  133. data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
  134. data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
  135. data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
  136. data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
  137. data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
  138. data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
  139. data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
  140. data/ext/lemongraph/arc_map.cc +1007 -0
  141. data/ext/lemongraph/digraph.cc +282 -0
  142. data/ext/lemongraph/digraph_arc.cc +153 -0
  143. data/ext/lemongraph/digraph_node.cc +277 -0
  144. data/ext/lemongraph/edge_map.cc +770 -0
  145. data/ext/lemongraph/extconf.rb +53 -0
  146. data/ext/lemongraph/graph.cc +351 -0
  147. data/ext/lemongraph/graph_arc.cc +95 -0
  148. data/ext/lemongraph/graph_edge.cc +153 -0
  149. data/ext/lemongraph/graph_item.cc +76 -0
  150. data/ext/lemongraph/graph_node.cc +321 -0
  151. data/ext/lemongraph/lemongraph.cc +260 -0
  152. data/ext/lemongraph/lemongraph.hh +295 -0
  153. data/ext/lemongraph/lemongraph.map +6 -0
  154. data/ext/lemongraph/lemongraph_export.hh +31 -0
  155. data/ext/lemongraph/node_map.cc +1011 -0
  156. data/lemongraph.gemspec +176 -0
  157. data/lib/lemongraph/graphviz.rb +240 -0
  158. data/lib/lemongraph/version.rb +4 -0
  159. data/lib/lemongraph.rb +21 -0
  160. data/samples/lemondeps.rb +38 -0
  161. metadata +202 -0
@@ -0,0 +1,1824 @@
1
+ /* -*- mode: C++; indent-tabs-mode: nil; -*-
2
+ *
3
+ * This file is a part of LEMON, a generic C++ optimization library.
4
+ *
5
+ * Copyright (C) 2003-2013
6
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
+ *
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.
12
+ *
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
15
+ * purpose.
16
+ *
17
+ */
18
+
19
+ #ifndef LEMON_UNION_FIND_H
20
+ #define LEMON_UNION_FIND_H
21
+
22
+ //!\ingroup auxdat
23
+ //!\file
24
+ //!\brief Union-Find data structures.
25
+ //!
26
+
27
+ #include <vector>
28
+ #include <list>
29
+ #include <utility>
30
+ #include <algorithm>
31
+ #include <functional>
32
+
33
+ #include <lemon/core.h>
34
+
35
+ namespace lemon {
36
+
37
+ /// \ingroup auxdat
38
+ ///
39
+ /// \brief A \e Union-Find data structure implementation
40
+ ///
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.
47
+ ///
48
+ /// It is primarily used in Kruskal algorithm for finding minimal
49
+ /// cost spanning tree in a graph.
50
+ /// \sa kruskal()
51
+ ///
52
+ /// \pre You need to add all the elements by the \ref insert()
53
+ /// method.
54
+ template <typename IM>
55
+ class UnionFind {
56
+ public:
57
+
58
+ ///\e
59
+ typedef IM ItemIntMap;
60
+ ///\e
61
+ typedef typename ItemIntMap::Key Item;
62
+
63
+ private:
64
+ // If the items vector stores negative value for an item then
65
+ // that item is root item and it has -items[it] component size.
66
+ // Else the items[it] contains the index of the parent.
67
+ std::vector<int> items;
68
+ ItemIntMap& index;
69
+
70
+ bool rep(int idx) const {
71
+ return items[idx] < 0;
72
+ }
73
+
74
+ int repIndex(int idx) const {
75
+ int k = idx;
76
+ while (!rep(k)) {
77
+ k = items[k] ;
78
+ }
79
+ while (idx != k) {
80
+ int next = items[idx];
81
+ const_cast<int&>(items[idx]) = k;
82
+ idx = next;
83
+ }
84
+ return k;
85
+ }
86
+
87
+ public:
88
+
89
+ /// \brief Constructor
90
+ ///
91
+ /// Constructor of the UnionFind class. You should give an item to
92
+ /// integer map which will be used from the data structure. If you
93
+ /// modify directly this map that may cause segmentation fault,
94
+ /// invalid data structure, or infinite loop when you use again
95
+ /// the union-find.
96
+ UnionFind(ItemIntMap& m) : index(m) {}
97
+
98
+ /// \brief Returns the index of the element's component.
99
+ ///
100
+ /// The method returns the index of the element's component.
101
+ /// This is an integer between zero and the number of inserted elements.
102
+ ///
103
+ int find(const Item& a) {
104
+ return repIndex(index[a]);
105
+ }
106
+
107
+ /// \brief Clears the union-find data structure
108
+ ///
109
+ /// Erase each item from the data structure.
110
+ void clear() {
111
+ items.clear();
112
+ }
113
+
114
+ /// \brief Inserts a new element into the structure.
115
+ ///
116
+ /// This method inserts a new element into the data structure.
117
+ ///
118
+ /// The method returns the index of the new component.
119
+ int insert(const Item& a) {
120
+ int n = items.size();
121
+ items.push_back(-1);
122
+ index.set(a,n);
123
+ return n;
124
+ }
125
+
126
+ /// \brief Joining the components of element \e a and element \e b.
127
+ ///
128
+ /// This is the \e union operation of the Union-Find structure.
129
+ /// Joins the component of element \e a and component of
130
+ /// element \e b. If \e a and \e b are in the same component then
131
+ /// it returns false otherwise it returns true.
132
+ bool join(const Item& a, const Item& b) {
133
+ int ka = repIndex(index[a]);
134
+ int kb = repIndex(index[b]);
135
+
136
+ if ( ka == kb )
137
+ return false;
138
+
139
+ if (items[ka] < items[kb]) {
140
+ items[ka] += items[kb];
141
+ items[kb] = ka;
142
+ } else {
143
+ items[kb] += items[ka];
144
+ items[ka] = kb;
145
+ }
146
+ return true;
147
+ }
148
+
149
+ /// \brief Returns the size of the component of element \e a.
150
+ ///
151
+ /// Returns the size of the component of element \e a.
152
+ int size(const Item& a) {
153
+ int k = repIndex(index[a]);
154
+ return - items[k];
155
+ }
156
+
157
+ };
158
+
159
+ /// \ingroup auxdat
160
+ ///
161
+ /// \brief A \e Union-Find data structure implementation which
162
+ /// is able to enumerate the components.
163
+ ///
164
+ /// The class implements a \e Union-Find data structure
165
+ /// which is able to enumerate the components and the items in
166
+ /// a component. If you don't need this feature then perhaps it's
167
+ /// better to use the \ref UnionFind class which is more efficient.
168
+ ///
169
+ /// The union operation uses rank heuristic, while
170
+ /// the find operation uses path compression.
171
+ ///
172
+ /// \pre You need to add all the elements by the \ref insert()
173
+ /// method.
174
+ ///
175
+ template <typename IM>
176
+ class UnionFindEnum {
177
+ public:
178
+
179
+ ///\e
180
+ typedef IM ItemIntMap;
181
+ ///\e
182
+ typedef typename ItemIntMap::Key Item;
183
+
184
+ private:
185
+
186
+ ItemIntMap& index;
187
+
188
+ // If the parent stores negative value for an item then that item
189
+ // is root item and it has ~(items[it].parent) component id. Else
190
+ // the items[it].parent contains the index of the parent.
191
+ //
192
+ // The \c next and \c prev provides the double-linked
193
+ // cyclic list of one component's items.
194
+ struct ItemT {
195
+ int parent;
196
+ Item item;
197
+
198
+ int next, prev;
199
+ };
200
+
201
+ std::vector<ItemT> items;
202
+ int firstFreeItem;
203
+
204
+ struct ClassT {
205
+ int size;
206
+ int firstItem;
207
+ int next, prev;
208
+ };
209
+
210
+ std::vector<ClassT> classes;
211
+ int firstClass, firstFreeClass;
212
+
213
+ int newClass() {
214
+ if (firstFreeClass == -1) {
215
+ int cdx = classes.size();
216
+ classes.push_back(ClassT());
217
+ return cdx;
218
+ } else {
219
+ int cdx = firstFreeClass;
220
+ firstFreeClass = classes[firstFreeClass].next;
221
+ return cdx;
222
+ }
223
+ }
224
+
225
+ int newItem() {
226
+ if (firstFreeItem == -1) {
227
+ int idx = items.size();
228
+ items.push_back(ItemT());
229
+ return idx;
230
+ } else {
231
+ int idx = firstFreeItem;
232
+ firstFreeItem = items[firstFreeItem].next;
233
+ return idx;
234
+ }
235
+ }
236
+
237
+
238
+ bool rep(int idx) const {
239
+ return items[idx].parent < 0;
240
+ }
241
+
242
+ int repIndex(int idx) const {
243
+ int k = idx;
244
+ while (!rep(k)) {
245
+ k = items[k].parent;
246
+ }
247
+ while (idx != k) {
248
+ int next = items[idx].parent;
249
+ const_cast<int&>(items[idx].parent) = k;
250
+ idx = next;
251
+ }
252
+ return k;
253
+ }
254
+
255
+ int classIndex(int idx) const {
256
+ return ~(items[repIndex(idx)].parent);
257
+ }
258
+
259
+ void singletonItem(int idx) {
260
+ items[idx].next = idx;
261
+ items[idx].prev = idx;
262
+ }
263
+
264
+ void laceItem(int idx, int rdx) {
265
+ items[idx].prev = rdx;
266
+ items[idx].next = items[rdx].next;
267
+ items[items[rdx].next].prev = idx;
268
+ items[rdx].next = idx;
269
+ }
270
+
271
+ void unlaceItem(int idx) {
272
+ items[items[idx].prev].next = items[idx].next;
273
+ items[items[idx].next].prev = items[idx].prev;
274
+
275
+ items[idx].next = firstFreeItem;
276
+ firstFreeItem = idx;
277
+ }
278
+
279
+ void spliceItems(int ak, int bk) {
280
+ items[items[ak].prev].next = bk;
281
+ items[items[bk].prev].next = ak;
282
+ int tmp = items[ak].prev;
283
+ items[ak].prev = items[bk].prev;
284
+ items[bk].prev = tmp;
285
+
286
+ }
287
+
288
+ void laceClass(int cls) {
289
+ if (firstClass != -1) {
290
+ classes[firstClass].prev = cls;
291
+ }
292
+ classes[cls].next = firstClass;
293
+ classes[cls].prev = -1;
294
+ firstClass = cls;
295
+ }
296
+
297
+ void unlaceClass(int cls) {
298
+ if (classes[cls].prev != -1) {
299
+ classes[classes[cls].prev].next = classes[cls].next;
300
+ } else {
301
+ firstClass = classes[cls].next;
302
+ }
303
+ if (classes[cls].next != -1) {
304
+ classes[classes[cls].next].prev = classes[cls].prev;
305
+ }
306
+
307
+ classes[cls].next = firstFreeClass;
308
+ firstFreeClass = cls;
309
+ }
310
+
311
+ public:
312
+
313
+ UnionFindEnum(ItemIntMap& _index)
314
+ : index(_index), items(), firstFreeItem(-1),
315
+ firstClass(-1), firstFreeClass(-1) {}
316
+
317
+ /// \brief Inserts the given element into a new component.
318
+ ///
319
+ /// This method creates a new component consisting only of the
320
+ /// given element.
321
+ ///
322
+ int insert(const Item& item) {
323
+ int idx = newItem();
324
+
325
+ index.set(item, idx);
326
+
327
+ singletonItem(idx);
328
+ items[idx].item = item;
329
+
330
+ int cdx = newClass();
331
+
332
+ items[idx].parent = ~cdx;
333
+
334
+ laceClass(cdx);
335
+ classes[cdx].size = 1;
336
+ classes[cdx].firstItem = idx;
337
+
338
+ firstClass = cdx;
339
+
340
+ return cdx;
341
+ }
342
+
343
+ /// \brief Inserts the given element into the component of the others.
344
+ ///
345
+ /// This methods inserts the element \e a into the component of the
346
+ /// element \e comp.
347
+ void insert(const Item& item, int cls) {
348
+ int rdx = classes[cls].firstItem;
349
+ int idx = newItem();
350
+
351
+ index.set(item, idx);
352
+
353
+ laceItem(idx, rdx);
354
+
355
+ items[idx].item = item;
356
+ items[idx].parent = rdx;
357
+
358
+ ++classes[~(items[rdx].parent)].size;
359
+ }
360
+
361
+ /// \brief Clears the union-find data structure
362
+ ///
363
+ /// Erase each item from the data structure.
364
+ void clear() {
365
+ items.clear();
366
+ firstClass = -1;
367
+ firstFreeItem = -1;
368
+ }
369
+
370
+ /// \brief Finds the component of the given element.
371
+ ///
372
+ /// The method returns the component id of the given element.
373
+ int find(const Item &item) const {
374
+ return ~(items[repIndex(index[item])].parent);
375
+ }
376
+
377
+ /// \brief Joining the component of element \e a and element \e b.
378
+ ///
379
+ /// This is the \e union operation of the Union-Find structure.
380
+ /// Joins the component of element \e a and component of
381
+ /// element \e b. If \e a and \e b are in the same component then
382
+ /// returns -1 else returns the remaining class.
383
+ int join(const Item& a, const Item& b) {
384
+
385
+ int ak = repIndex(index[a]);
386
+ int bk = repIndex(index[b]);
387
+
388
+ if (ak == bk) {
389
+ return -1;
390
+ }
391
+
392
+ int acx = ~(items[ak].parent);
393
+ int bcx = ~(items[bk].parent);
394
+
395
+ int rcx;
396
+
397
+ if (classes[acx].size > classes[bcx].size) {
398
+ classes[acx].size += classes[bcx].size;
399
+ items[bk].parent = ak;
400
+ unlaceClass(bcx);
401
+ rcx = acx;
402
+ } else {
403
+ classes[bcx].size += classes[acx].size;
404
+ items[ak].parent = bk;
405
+ unlaceClass(acx);
406
+ rcx = bcx;
407
+ }
408
+ spliceItems(ak, bk);
409
+
410
+ return rcx;
411
+ }
412
+
413
+ /// \brief Returns the size of the class.
414
+ ///
415
+ /// Returns the size of the class.
416
+ int size(int cls) const {
417
+ return classes[cls].size;
418
+ }
419
+
420
+ /// \brief Splits up the component.
421
+ ///
422
+ /// Splitting the component into singleton components (component
423
+ /// of size one).
424
+ void split(int cls) {
425
+ int fdx = classes[cls].firstItem;
426
+ int idx = items[fdx].next;
427
+ while (idx != fdx) {
428
+ int next = items[idx].next;
429
+
430
+ singletonItem(idx);
431
+
432
+ int cdx = newClass();
433
+ items[idx].parent = ~cdx;
434
+
435
+ laceClass(cdx);
436
+ classes[cdx].size = 1;
437
+ classes[cdx].firstItem = idx;
438
+
439
+ idx = next;
440
+ }
441
+
442
+ items[idx].prev = idx;
443
+ items[idx].next = idx;
444
+
445
+ classes[~(items[idx].parent)].size = 1;
446
+
447
+ }
448
+
449
+ /// \brief Removes the given element from the structure.
450
+ ///
451
+ /// Removes the element from its component and if the component becomes
452
+ /// empty then removes that component from the component list.
453
+ ///
454
+ /// \warning It is an error to remove an element which is not in
455
+ /// the structure.
456
+ /// \warning This running time of this operation is proportional to the
457
+ /// number of the items in this class.
458
+ void erase(const Item& item) {
459
+ int idx = index[item];
460
+ int fdx = items[idx].next;
461
+
462
+ int cdx = classIndex(idx);
463
+ if (idx == fdx) {
464
+ unlaceClass(cdx);
465
+ items[idx].next = firstFreeItem;
466
+ firstFreeItem = idx;
467
+ return;
468
+ } else {
469
+ classes[cdx].firstItem = fdx;
470
+ --classes[cdx].size;
471
+ items[fdx].parent = ~cdx;
472
+
473
+ unlaceItem(idx);
474
+ idx = items[fdx].next;
475
+ while (idx != fdx) {
476
+ items[idx].parent = fdx;
477
+ idx = items[idx].next;
478
+ }
479
+
480
+ }
481
+
482
+ }
483
+
484
+ /// \brief Gives back a representant item of the component.
485
+ ///
486
+ /// Gives back a representant item of the component.
487
+ Item item(int cls) const {
488
+ return items[classes[cls].firstItem].item;
489
+ }
490
+
491
+ /// \brief Removes the component of the given element from the structure.
492
+ ///
493
+ /// Removes the component of the given element from the structure.
494
+ ///
495
+ /// \warning It is an error to give an element which is not in the
496
+ /// structure.
497
+ void eraseClass(int cls) {
498
+ int fdx = classes[cls].firstItem;
499
+ unlaceClass(cls);
500
+ items[items[fdx].prev].next = firstFreeItem;
501
+ firstFreeItem = fdx;
502
+ }
503
+
504
+ /// \brief LEMON style iterator for the representant items.
505
+ ///
506
+ /// ClassIt is a lemon style iterator for the components. It iterates
507
+ /// on the ids of the classes.
508
+ class ClassIt {
509
+ public:
510
+ /// \brief Constructor of the iterator
511
+ ///
512
+ /// Constructor of the iterator
513
+ ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
514
+ cdx = unionFind->firstClass;
515
+ }
516
+
517
+ /// \brief Constructor to get invalid iterator
518
+ ///
519
+ /// Constructor to get invalid iterator
520
+ ClassIt(Invalid) : unionFind(0), cdx(-1) {}
521
+
522
+ /// \brief Increment operator
523
+ ///
524
+ /// It steps to the next representant item.
525
+ ClassIt& operator++() {
526
+ cdx = unionFind->classes[cdx].next;
527
+ return *this;
528
+ }
529
+
530
+ /// \brief Conversion operator
531
+ ///
532
+ /// It converts the iterator to the current representant item.
533
+ operator int() const {
534
+ return cdx;
535
+ }
536
+
537
+ /// \brief Equality operator
538
+ ///
539
+ /// Equality operator
540
+ bool operator==(const ClassIt& i) {
541
+ return i.cdx == cdx;
542
+ }
543
+
544
+ /// \brief Inequality operator
545
+ ///
546
+ /// Inequality operator
547
+ bool operator!=(const ClassIt& i) {
548
+ return i.cdx != cdx;
549
+ }
550
+
551
+ private:
552
+ const UnionFindEnum* unionFind;
553
+ int cdx;
554
+ };
555
+
556
+ /// \brief LEMON style iterator for the items of a component.
557
+ ///
558
+ /// ClassIt is a lemon style iterator for the components. It iterates
559
+ /// on the items of a class. By example if you want to iterate on
560
+ /// each items of each classes then you may write the next code.
561
+ ///\code
562
+ /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
563
+ /// std::cout << "Class: ";
564
+ /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
565
+ /// std::cout << toString(iit) << ' ' << std::endl;
566
+ /// }
567
+ /// std::cout << std::endl;
568
+ /// }
569
+ ///\endcode
570
+ class ItemIt {
571
+ public:
572
+ /// \brief Constructor of the iterator
573
+ ///
574
+ /// Constructor of the iterator. The iterator iterates
575
+ /// on the class of the \c item.
576
+ ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
577
+ fdx = idx = unionFind->classes[cls].firstItem;
578
+ }
579
+
580
+ /// \brief Constructor to get invalid iterator
581
+ ///
582
+ /// Constructor to get invalid iterator
583
+ ItemIt(Invalid) : unionFind(0), idx(-1) {}
584
+
585
+ /// \brief Increment operator
586
+ ///
587
+ /// It steps to the next item in the class.
588
+ ItemIt& operator++() {
589
+ idx = unionFind->items[idx].next;
590
+ if (idx == fdx) idx = -1;
591
+ return *this;
592
+ }
593
+
594
+ /// \brief Conversion operator
595
+ ///
596
+ /// It converts the iterator to the current item.
597
+ operator const Item&() const {
598
+ return unionFind->items[idx].item;
599
+ }
600
+
601
+ /// \brief Equality operator
602
+ ///
603
+ /// Equality operator
604
+ bool operator==(const ItemIt& i) {
605
+ return i.idx == idx;
606
+ }
607
+
608
+ /// \brief Inequality operator
609
+ ///
610
+ /// Inequality operator
611
+ bool operator!=(const ItemIt& i) {
612
+ return i.idx != idx;
613
+ }
614
+
615
+ private:
616
+ const UnionFindEnum* unionFind;
617
+ int idx, fdx;
618
+ };
619
+
620
+ };
621
+
622
+ /// \ingroup auxdat
623
+ ///
624
+ /// \brief A \e Extend-Find data structure implementation which
625
+ /// is able to enumerate the components.
626
+ ///
627
+ /// The class implements an \e Extend-Find data structure which is
628
+ /// able to enumerate the components and the items in a
629
+ /// component. The data structure is a simplification of the
630
+ /// Union-Find structure, and it does not allow to merge two components.
631
+ ///
632
+ /// \pre You need to add all the elements by the \ref insert()
633
+ /// method.
634
+ template <typename IM>
635
+ class ExtendFindEnum {
636
+ public:
637
+
638
+ ///\e
639
+ typedef IM ItemIntMap;
640
+ ///\e
641
+ typedef typename ItemIntMap::Key Item;
642
+
643
+ private:
644
+
645
+ ItemIntMap& index;
646
+
647
+ struct ItemT {
648
+ int cls;
649
+ Item item;
650
+ int next, prev;
651
+ };
652
+
653
+ std::vector<ItemT> items;
654
+ int firstFreeItem;
655
+
656
+ struct ClassT {
657
+ int firstItem;
658
+ int next, prev;
659
+ };
660
+
661
+ std::vector<ClassT> classes;
662
+
663
+ int firstClass, firstFreeClass;
664
+
665
+ int newClass() {
666
+ if (firstFreeClass != -1) {
667
+ int cdx = firstFreeClass;
668
+ firstFreeClass = classes[cdx].next;
669
+ return cdx;
670
+ } else {
671
+ classes.push_back(ClassT());
672
+ return classes.size() - 1;
673
+ }
674
+ }
675
+
676
+ int newItem() {
677
+ if (firstFreeItem != -1) {
678
+ int idx = firstFreeItem;
679
+ firstFreeItem = items[idx].next;
680
+ return idx;
681
+ } else {
682
+ items.push_back(ItemT());
683
+ return items.size() - 1;
684
+ }
685
+ }
686
+
687
+ public:
688
+
689
+ /// \brief Constructor
690
+ ExtendFindEnum(ItemIntMap& _index)
691
+ : index(_index), items(), firstFreeItem(-1),
692
+ classes(), firstClass(-1), firstFreeClass(-1) {}
693
+
694
+ /// \brief Inserts the given element into a new component.
695
+ ///
696
+ /// This method creates a new component consisting only of the
697
+ /// given element.
698
+ int insert(const Item& item) {
699
+ int cdx = newClass();
700
+ classes[cdx].prev = -1;
701
+ classes[cdx].next = firstClass;
702
+ if (firstClass != -1) {
703
+ classes[firstClass].prev = cdx;
704
+ }
705
+ firstClass = cdx;
706
+
707
+ int idx = newItem();
708
+ items[idx].item = item;
709
+ items[idx].cls = cdx;
710
+ items[idx].prev = idx;
711
+ items[idx].next = idx;
712
+
713
+ classes[cdx].firstItem = idx;
714
+
715
+ index.set(item, idx);
716
+
717
+ return cdx;
718
+ }
719
+
720
+ /// \brief Inserts the given element into the given component.
721
+ ///
722
+ /// This methods inserts the element \e item a into the \e cls class.
723
+ void insert(const Item& item, int cls) {
724
+ int idx = newItem();
725
+ int rdx = classes[cls].firstItem;
726
+ items[idx].item = item;
727
+ items[idx].cls = cls;
728
+
729
+ items[idx].prev = rdx;
730
+ items[idx].next = items[rdx].next;
731
+ items[items[rdx].next].prev = idx;
732
+ items[rdx].next = idx;
733
+
734
+ index.set(item, idx);
735
+ }
736
+
737
+ /// \brief Clears the union-find data structure
738
+ ///
739
+ /// Erase each item from the data structure.
740
+ void clear() {
741
+ items.clear();
742
+ classes.clear();
743
+ firstClass = firstFreeClass = firstFreeItem = -1;
744
+ }
745
+
746
+ /// \brief Gives back the class of the \e item.
747
+ ///
748
+ /// Gives back the class of the \e item.
749
+ int find(const Item &item) const {
750
+ return items[index[item]].cls;
751
+ }
752
+
753
+ /// \brief Gives back a representant item of the component.
754
+ ///
755
+ /// Gives back a representant item of the component.
756
+ Item item(int cls) const {
757
+ return items[classes[cls].firstItem].item;
758
+ }
759
+
760
+ /// \brief Removes the given element from the structure.
761
+ ///
762
+ /// Removes the element from its component and if the component becomes
763
+ /// empty then removes that component from the component list.
764
+ ///
765
+ /// \warning It is an error to remove an element which is not in
766
+ /// the structure.
767
+ void erase(const Item &item) {
768
+ int idx = index[item];
769
+ int cdx = items[idx].cls;
770
+
771
+ if (idx == items[idx].next) {
772
+ if (classes[cdx].prev != -1) {
773
+ classes[classes[cdx].prev].next = classes[cdx].next;
774
+ } else {
775
+ firstClass = classes[cdx].next;
776
+ }
777
+ if (classes[cdx].next != -1) {
778
+ classes[classes[cdx].next].prev = classes[cdx].prev;
779
+ }
780
+ classes[cdx].next = firstFreeClass;
781
+ firstFreeClass = cdx;
782
+ } else {
783
+ classes[cdx].firstItem = items[idx].next;
784
+ items[items[idx].next].prev = items[idx].prev;
785
+ items[items[idx].prev].next = items[idx].next;
786
+ }
787
+ items[idx].next = firstFreeItem;
788
+ firstFreeItem = idx;
789
+
790
+ }
791
+
792
+
793
+ /// \brief Removes the component of the given element from the structure.
794
+ ///
795
+ /// Removes the component of the given element from the structure.
796
+ ///
797
+ /// \warning It is an error to give an element which is not in the
798
+ /// structure.
799
+ void eraseClass(int cdx) {
800
+ int idx = classes[cdx].firstItem;
801
+ items[items[idx].prev].next = firstFreeItem;
802
+ firstFreeItem = idx;
803
+
804
+ if (classes[cdx].prev != -1) {
805
+ classes[classes[cdx].prev].next = classes[cdx].next;
806
+ } else {
807
+ firstClass = classes[cdx].next;
808
+ }
809
+ if (classes[cdx].next != -1) {
810
+ classes[classes[cdx].next].prev = classes[cdx].prev;
811
+ }
812
+ classes[cdx].next = firstFreeClass;
813
+ firstFreeClass = cdx;
814
+ }
815
+
816
+ /// \brief LEMON style iterator for the classes.
817
+ ///
818
+ /// ClassIt is a lemon style iterator for the components. It iterates
819
+ /// on the ids of classes.
820
+ class ClassIt {
821
+ public:
822
+ /// \brief Constructor of the iterator
823
+ ///
824
+ /// Constructor of the iterator
825
+ ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
826
+ cdx = extendFind->firstClass;
827
+ }
828
+
829
+ /// \brief Constructor to get invalid iterator
830
+ ///
831
+ /// Constructor to get invalid iterator
832
+ ClassIt(Invalid) : extendFind(0), cdx(-1) {}
833
+
834
+ /// \brief Increment operator
835
+ ///
836
+ /// It steps to the next representant item.
837
+ ClassIt& operator++() {
838
+ cdx = extendFind->classes[cdx].next;
839
+ return *this;
840
+ }
841
+
842
+ /// \brief Conversion operator
843
+ ///
844
+ /// It converts the iterator to the current class id.
845
+ operator int() const {
846
+ return cdx;
847
+ }
848
+
849
+ /// \brief Equality operator
850
+ ///
851
+ /// Equality operator
852
+ bool operator==(const ClassIt& i) {
853
+ return i.cdx == cdx;
854
+ }
855
+
856
+ /// \brief Inequality operator
857
+ ///
858
+ /// Inequality operator
859
+ bool operator!=(const ClassIt& i) {
860
+ return i.cdx != cdx;
861
+ }
862
+
863
+ private:
864
+ const ExtendFindEnum* extendFind;
865
+ int cdx;
866
+ };
867
+
868
+ /// \brief LEMON style iterator for the items of a component.
869
+ ///
870
+ /// ClassIt is a lemon style iterator for the components. It iterates
871
+ /// on the items of a class. By example if you want to iterate on
872
+ /// each items of each classes then you may write the next code.
873
+ ///\code
874
+ /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
875
+ /// std::cout << "Class: ";
876
+ /// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
877
+ /// std::cout << toString(iit) << ' ' << std::endl;
878
+ /// }
879
+ /// std::cout << std::endl;
880
+ /// }
881
+ ///\endcode
882
+ class ItemIt {
883
+ public:
884
+ /// \brief Constructor of the iterator
885
+ ///
886
+ /// Constructor of the iterator. The iterator iterates
887
+ /// on the class of the \c item.
888
+ ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
889
+ fdx = idx = extendFind->classes[cls].firstItem;
890
+ }
891
+
892
+ /// \brief Constructor to get invalid iterator
893
+ ///
894
+ /// Constructor to get invalid iterator
895
+ ItemIt(Invalid) : extendFind(0), idx(-1) {}
896
+
897
+ /// \brief Increment operator
898
+ ///
899
+ /// It steps to the next item in the class.
900
+ ItemIt& operator++() {
901
+ idx = extendFind->items[idx].next;
902
+ if (fdx == idx) idx = -1;
903
+ return *this;
904
+ }
905
+
906
+ /// \brief Conversion operator
907
+ ///
908
+ /// It converts the iterator to the current item.
909
+ operator const Item&() const {
910
+ return extendFind->items[idx].item;
911
+ }
912
+
913
+ /// \brief Equality operator
914
+ ///
915
+ /// Equality operator
916
+ bool operator==(const ItemIt& i) {
917
+ return i.idx == idx;
918
+ }
919
+
920
+ /// \brief Inequality operator
921
+ ///
922
+ /// Inequality operator
923
+ bool operator!=(const ItemIt& i) {
924
+ return i.idx != idx;
925
+ }
926
+
927
+ private:
928
+ const ExtendFindEnum* extendFind;
929
+ int idx, fdx;
930
+ };
931
+
932
+ };
933
+
934
+ /// \ingroup auxdat
935
+ ///
936
+ /// \brief A \e Union-Find data structure implementation which
937
+ /// is able to store a priority for each item and retrieve the minimum of
938
+ /// each class.
939
+ ///
940
+ /// A \e Union-Find data structure implementation which is able to
941
+ /// store a priority for each item and retrieve the minimum of each
942
+ /// class. In addition, it supports the joining and splitting the
943
+ /// components. If you don't need this feature then you makes
944
+ /// better to use the \ref UnionFind class which is more efficient.
945
+ ///
946
+ /// The union-find data strcuture based on a (2, 16)-tree with a
947
+ /// tournament minimum selection on the internal nodes. The insert
948
+ /// operation takes O(1), the find, set, decrease and increase takes
949
+ /// O(log(n)), where n is the number of nodes in the current
950
+ /// component. The complexity of join and split is O(log(n)*k),
951
+ /// where n is the sum of the number of the nodes and k is the
952
+ /// number of joined components or the number of the components
953
+ /// after the split.
954
+ ///
955
+ /// \pre You need to add all the elements by the \ref insert()
956
+ /// method.
957
+ template <typename V, typename IM, typename Comp = std::less<V> >
958
+ class HeapUnionFind {
959
+ public:
960
+
961
+ ///\e
962
+ typedef V Value;
963
+ ///\e
964
+ typedef typename IM::Key Item;
965
+ ///\e
966
+ typedef IM ItemIntMap;
967
+ ///\e
968
+ typedef Comp Compare;
969
+
970
+ private:
971
+
972
+ static const int cmax = 16;
973
+
974
+ ItemIntMap& index;
975
+
976
+ struct ClassNode {
977
+ int parent;
978
+ int depth;
979
+
980
+ int left, right;
981
+ int next, prev;
982
+ };
983
+
984
+ int first_class;
985
+ int first_free_class;
986
+ std::vector<ClassNode> classes;
987
+
988
+ int newClass() {
989
+ if (first_free_class < 0) {
990
+ int id = classes.size();
991
+ classes.push_back(ClassNode());
992
+ return id;
993
+ } else {
994
+ int id = first_free_class;
995
+ first_free_class = classes[id].next;
996
+ return id;
997
+ }
998
+ }
999
+
1000
+ void deleteClass(int id) {
1001
+ classes[id].next = first_free_class;
1002
+ first_free_class = id;
1003
+ }
1004
+
1005
+ struct ItemNode {
1006
+ int parent;
1007
+ Item item;
1008
+ Value prio;
1009
+ int next, prev;
1010
+ int left, right;
1011
+ int size;
1012
+ };
1013
+
1014
+ int first_free_node;
1015
+ std::vector<ItemNode> nodes;
1016
+
1017
+ int newNode() {
1018
+ if (first_free_node < 0) {
1019
+ int id = nodes.size();
1020
+ nodes.push_back(ItemNode());
1021
+ return id;
1022
+ } else {
1023
+ int id = first_free_node;
1024
+ first_free_node = nodes[id].next;
1025
+ return id;
1026
+ }
1027
+ }
1028
+
1029
+ void deleteNode(int id) {
1030
+ nodes[id].next = first_free_node;
1031
+ first_free_node = id;
1032
+ }
1033
+
1034
+ Comp comp;
1035
+
1036
+ int findClass(int id) const {
1037
+ int kd = id;
1038
+ while (kd >= 0) {
1039
+ kd = nodes[kd].parent;
1040
+ }
1041
+ return ~kd;
1042
+ }
1043
+
1044
+ int leftNode(int id) const {
1045
+ int kd = ~(classes[id].parent);
1046
+ for (int i = 0; i < classes[id].depth; ++i) {
1047
+ kd = nodes[kd].left;
1048
+ }
1049
+ return kd;
1050
+ }
1051
+
1052
+ int nextNode(int id) const {
1053
+ int depth = 0;
1054
+ while (id >= 0 && nodes[id].next == -1) {
1055
+ id = nodes[id].parent;
1056
+ ++depth;
1057
+ }
1058
+ if (id < 0) {
1059
+ return -1;
1060
+ }
1061
+ id = nodes[id].next;
1062
+ while (depth--) {
1063
+ id = nodes[id].left;
1064
+ }
1065
+ return id;
1066
+ }
1067
+
1068
+
1069
+ void setPrio(int id) {
1070
+ int jd = nodes[id].left;
1071
+ nodes[id].prio = nodes[jd].prio;
1072
+ nodes[id].item = nodes[jd].item;
1073
+ jd = nodes[jd].next;
1074
+ while (jd != -1) {
1075
+ if (comp(nodes[jd].prio, nodes[id].prio)) {
1076
+ nodes[id].prio = nodes[jd].prio;
1077
+ nodes[id].item = nodes[jd].item;
1078
+ }
1079
+ jd = nodes[jd].next;
1080
+ }
1081
+ }
1082
+
1083
+ void push(int id, int jd) {
1084
+ nodes[id].size = 1;
1085
+ nodes[id].left = nodes[id].right = jd;
1086
+ nodes[jd].next = nodes[jd].prev = -1;
1087
+ nodes[jd].parent = id;
1088
+ }
1089
+
1090
+ void pushAfter(int id, int jd) {
1091
+ int kd = nodes[id].parent;
1092
+ if (nodes[id].next != -1) {
1093
+ nodes[nodes[id].next].prev = jd;
1094
+ if (kd >= 0) {
1095
+ nodes[kd].size += 1;
1096
+ }
1097
+ } else {
1098
+ if (kd >= 0) {
1099
+ nodes[kd].right = jd;
1100
+ nodes[kd].size += 1;
1101
+ }
1102
+ }
1103
+ nodes[jd].next = nodes[id].next;
1104
+ nodes[jd].prev = id;
1105
+ nodes[id].next = jd;
1106
+ nodes[jd].parent = kd;
1107
+ }
1108
+
1109
+ void pushRight(int id, int jd) {
1110
+ nodes[id].size += 1;
1111
+ nodes[jd].prev = nodes[id].right;
1112
+ nodes[jd].next = -1;
1113
+ nodes[nodes[id].right].next = jd;
1114
+ nodes[id].right = jd;
1115
+ nodes[jd].parent = id;
1116
+ }
1117
+
1118
+ void popRight(int id) {
1119
+ nodes[id].size -= 1;
1120
+ int jd = nodes[id].right;
1121
+ nodes[nodes[jd].prev].next = -1;
1122
+ nodes[id].right = nodes[jd].prev;
1123
+ }
1124
+
1125
+ void splice(int id, int jd) {
1126
+ nodes[id].size += nodes[jd].size;
1127
+ nodes[nodes[id].right].next = nodes[jd].left;
1128
+ nodes[nodes[jd].left].prev = nodes[id].right;
1129
+ int kd = nodes[jd].left;
1130
+ while (kd != -1) {
1131
+ nodes[kd].parent = id;
1132
+ kd = nodes[kd].next;
1133
+ }
1134
+ nodes[id].right = nodes[jd].right;
1135
+ }
1136
+
1137
+ void split(int id, int jd) {
1138
+ int kd = nodes[id].parent;
1139
+ nodes[kd].right = nodes[id].prev;
1140
+ nodes[nodes[id].prev].next = -1;
1141
+
1142
+ nodes[jd].left = id;
1143
+ nodes[id].prev = -1;
1144
+ int num = 0;
1145
+ while (id != -1) {
1146
+ nodes[id].parent = jd;
1147
+ nodes[jd].right = id;
1148
+ id = nodes[id].next;
1149
+ ++num;
1150
+ }
1151
+ nodes[kd].size -= num;
1152
+ nodes[jd].size = num;
1153
+ }
1154
+
1155
+ void pushLeft(int id, int jd) {
1156
+ nodes[id].size += 1;
1157
+ nodes[jd].next = nodes[id].left;
1158
+ nodes[jd].prev = -1;
1159
+ nodes[nodes[id].left].prev = jd;
1160
+ nodes[id].left = jd;
1161
+ nodes[jd].parent = id;
1162
+ }
1163
+
1164
+ void popLeft(int id) {
1165
+ nodes[id].size -= 1;
1166
+ int jd = nodes[id].left;
1167
+ nodes[nodes[jd].next].prev = -1;
1168
+ nodes[id].left = nodes[jd].next;
1169
+ }
1170
+
1171
+ void repairLeft(int id) {
1172
+ int jd = ~(classes[id].parent);
1173
+ while (nodes[jd].left != -1) {
1174
+ int kd = nodes[jd].left;
1175
+ if (nodes[jd].size == 1) {
1176
+ if (nodes[jd].parent < 0) {
1177
+ classes[id].parent = ~kd;
1178
+ classes[id].depth -= 1;
1179
+ nodes[kd].parent = ~id;
1180
+ deleteNode(jd);
1181
+ jd = kd;
1182
+ } else {
1183
+ int pd = nodes[jd].parent;
1184
+ if (nodes[nodes[jd].next].size < cmax) {
1185
+ pushLeft(nodes[jd].next, nodes[jd].left);
1186
+ if (less(jd, nodes[jd].next) ||
1187
+ nodes[jd].item == nodes[pd].item) {
1188
+ nodes[nodes[jd].next].prio = nodes[jd].prio;
1189
+ nodes[nodes[jd].next].item = nodes[jd].item;
1190
+ }
1191
+ popLeft(pd);
1192
+ deleteNode(jd);
1193
+ jd = pd;
1194
+ } else {
1195
+ int ld = nodes[nodes[jd].next].left;
1196
+ popLeft(nodes[jd].next);
1197
+ pushRight(jd, ld);
1198
+ if (less(ld, nodes[jd].left) ||
1199
+ nodes[ld].item == nodes[pd].item) {
1200
+ nodes[jd].item = nodes[ld].item;
1201
+ nodes[jd].prio = nodes[ld].prio;
1202
+ }
1203
+ if (nodes[nodes[jd].next].item == nodes[ld].item) {
1204
+ setPrio(nodes[jd].next);
1205
+ }
1206
+ jd = nodes[jd].left;
1207
+ }
1208
+ }
1209
+ } else {
1210
+ jd = nodes[jd].left;
1211
+ }
1212
+ }
1213
+ }
1214
+
1215
+ void repairRight(int id) {
1216
+ int jd = ~(classes[id].parent);
1217
+ while (nodes[jd].right != -1) {
1218
+ int kd = nodes[jd].right;
1219
+ if (nodes[jd].size == 1) {
1220
+ if (nodes[jd].parent < 0) {
1221
+ classes[id].parent = ~kd;
1222
+ classes[id].depth -= 1;
1223
+ nodes[kd].parent = ~id;
1224
+ deleteNode(jd);
1225
+ jd = kd;
1226
+ } else {
1227
+ int pd = nodes[jd].parent;
1228
+ if (nodes[nodes[jd].prev].size < cmax) {
1229
+ pushRight(nodes[jd].prev, nodes[jd].right);
1230
+ if (less(jd, nodes[jd].prev) ||
1231
+ nodes[jd].item == nodes[pd].item) {
1232
+ nodes[nodes[jd].prev].prio = nodes[jd].prio;
1233
+ nodes[nodes[jd].prev].item = nodes[jd].item;
1234
+ }
1235
+ popRight(pd);
1236
+ deleteNode(jd);
1237
+ jd = pd;
1238
+ } else {
1239
+ int ld = nodes[nodes[jd].prev].right;
1240
+ popRight(nodes[jd].prev);
1241
+ pushLeft(jd, ld);
1242
+ if (less(ld, nodes[jd].right) ||
1243
+ nodes[ld].item == nodes[pd].item) {
1244
+ nodes[jd].item = nodes[ld].item;
1245
+ nodes[jd].prio = nodes[ld].prio;
1246
+ }
1247
+ if (nodes[nodes[jd].prev].item == nodes[ld].item) {
1248
+ setPrio(nodes[jd].prev);
1249
+ }
1250
+ jd = nodes[jd].right;
1251
+ }
1252
+ }
1253
+ } else {
1254
+ jd = nodes[jd].right;
1255
+ }
1256
+ }
1257
+ }
1258
+
1259
+
1260
+ bool less(int id, int jd) const {
1261
+ return comp(nodes[id].prio, nodes[jd].prio);
1262
+ }
1263
+
1264
+ public:
1265
+
1266
+ /// \brief Returns true when the given class is alive.
1267
+ ///
1268
+ /// Returns true when the given class is alive, ie. the class is
1269
+ /// not nested into other class.
1270
+ bool alive(int cls) const {
1271
+ return classes[cls].parent < 0;
1272
+ }
1273
+
1274
+ /// \brief Returns true when the given class is trivial.
1275
+ ///
1276
+ /// Returns true when the given class is trivial, ie. the class
1277
+ /// contains just one item directly.
1278
+ bool trivial(int cls) const {
1279
+ return classes[cls].left == -1;
1280
+ }
1281
+
1282
+ /// \brief Constructs the union-find.
1283
+ ///
1284
+ /// Constructs the union-find.
1285
+ /// \brief _index The index map of the union-find. The data
1286
+ /// structure uses internally for store references.
1287
+ HeapUnionFind(ItemIntMap& _index)
1288
+ : index(_index), first_class(-1),
1289
+ first_free_class(-1), first_free_node(-1) {}
1290
+
1291
+ /// \brief Clears the union-find data structure
1292
+ ///
1293
+ /// Erase each item from the data structure.
1294
+ void clear() {
1295
+ nodes.clear();
1296
+ classes.clear();
1297
+ first_free_node = first_free_class = first_class = -1;
1298
+ }
1299
+
1300
+ /// \brief Insert a new node into a new component.
1301
+ ///
1302
+ /// Insert a new node into a new component.
1303
+ /// \param item The item of the new node.
1304
+ /// \param prio The priority of the new node.
1305
+ /// \return The class id of the one-item-heap.
1306
+ int insert(const Item& item, const Value& prio) {
1307
+ int id = newNode();
1308
+ nodes[id].item = item;
1309
+ nodes[id].prio = prio;
1310
+ nodes[id].size = 0;
1311
+
1312
+ nodes[id].prev = -1;
1313
+ nodes[id].next = -1;
1314
+
1315
+ nodes[id].left = -1;
1316
+ nodes[id].right = -1;
1317
+
1318
+ nodes[id].item = item;
1319
+ index[item] = id;
1320
+
1321
+ int class_id = newClass();
1322
+ classes[class_id].parent = ~id;
1323
+ classes[class_id].depth = 0;
1324
+
1325
+ classes[class_id].left = -1;
1326
+ classes[class_id].right = -1;
1327
+
1328
+ if (first_class != -1) {
1329
+ classes[first_class].prev = class_id;
1330
+ }
1331
+ classes[class_id].next = first_class;
1332
+ classes[class_id].prev = -1;
1333
+ first_class = class_id;
1334
+
1335
+ nodes[id].parent = ~class_id;
1336
+
1337
+ return class_id;
1338
+ }
1339
+
1340
+ /// \brief The class of the item.
1341
+ ///
1342
+ /// \return The alive class id of the item, which is not nested into
1343
+ /// other classes.
1344
+ ///
1345
+ /// The time complexity is O(log(n)).
1346
+ int find(const Item& item) const {
1347
+ return findClass(index[item]);
1348
+ }
1349
+
1350
+ /// \brief Joins the classes.
1351
+ ///
1352
+ /// The current function joins the given classes. The parameter is
1353
+ /// an STL range which should be contains valid class ids. The
1354
+ /// time complexity is O(log(n)*k) where n is the overall number
1355
+ /// of the joined nodes and k is the number of classes.
1356
+ /// \return The class of the joined classes.
1357
+ /// \pre The range should contain at least two class ids.
1358
+ template <typename Iterator>
1359
+ int join(Iterator begin, Iterator end) {
1360
+ std::vector<int> cs;
1361
+ for (Iterator it = begin; it != end; ++it) {
1362
+ cs.push_back(*it);
1363
+ }
1364
+
1365
+ int class_id = newClass();
1366
+ { // creation union-find
1367
+
1368
+ if (first_class != -1) {
1369
+ classes[first_class].prev = class_id;
1370
+ }
1371
+ classes[class_id].next = first_class;
1372
+ classes[class_id].prev = -1;
1373
+ first_class = class_id;
1374
+
1375
+ classes[class_id].depth = classes[cs[0]].depth;
1376
+ classes[class_id].parent = classes[cs[0]].parent;
1377
+ nodes[~(classes[class_id].parent)].parent = ~class_id;
1378
+
1379
+ int l = cs[0];
1380
+
1381
+ classes[class_id].left = l;
1382
+ classes[class_id].right = l;
1383
+
1384
+ if (classes[l].next != -1) {
1385
+ classes[classes[l].next].prev = classes[l].prev;
1386
+ }
1387
+ classes[classes[l].prev].next = classes[l].next;
1388
+
1389
+ classes[l].prev = -1;
1390
+ classes[l].next = -1;
1391
+
1392
+ classes[l].depth = leftNode(l);
1393
+ classes[l].parent = class_id;
1394
+
1395
+ }
1396
+
1397
+ { // merging of heap
1398
+ int l = class_id;
1399
+ for (int ci = 1; ci < int(cs.size()); ++ci) {
1400
+ int r = cs[ci];
1401
+ int rln = leftNode(r);
1402
+ if (classes[l].depth > classes[r].depth) {
1403
+ int id = ~(classes[l].parent);
1404
+ for (int i = classes[r].depth + 1; i < classes[l].depth; ++i) {
1405
+ id = nodes[id].right;
1406
+ }
1407
+ while (id >= 0 && nodes[id].size == cmax) {
1408
+ int new_id = newNode();
1409
+ int right_id = nodes[id].right;
1410
+
1411
+ popRight(id);
1412
+ if (nodes[id].item == nodes[right_id].item) {
1413
+ setPrio(id);
1414
+ }
1415
+ push(new_id, right_id);
1416
+ pushRight(new_id, ~(classes[r].parent));
1417
+
1418
+ if (less(~classes[r].parent, right_id)) {
1419
+ nodes[new_id].item = nodes[~classes[r].parent].item;
1420
+ nodes[new_id].prio = nodes[~classes[r].parent].prio;
1421
+ } else {
1422
+ nodes[new_id].item = nodes[right_id].item;
1423
+ nodes[new_id].prio = nodes[right_id].prio;
1424
+ }
1425
+
1426
+ id = nodes[id].parent;
1427
+ classes[r].parent = ~new_id;
1428
+ }
1429
+ if (id < 0) {
1430
+ int new_parent = newNode();
1431
+ nodes[new_parent].next = -1;
1432
+ nodes[new_parent].prev = -1;
1433
+ nodes[new_parent].parent = ~l;
1434
+
1435
+ push(new_parent, ~(classes[l].parent));
1436
+ pushRight(new_parent, ~(classes[r].parent));
1437
+ setPrio(new_parent);
1438
+
1439
+ classes[l].parent = ~new_parent;
1440
+ classes[l].depth += 1;
1441
+ } else {
1442
+ pushRight(id, ~(classes[r].parent));
1443
+ while (id >= 0 && less(~(classes[r].parent), id)) {
1444
+ nodes[id].prio = nodes[~(classes[r].parent)].prio;
1445
+ nodes[id].item = nodes[~(classes[r].parent)].item;
1446
+ id = nodes[id].parent;
1447
+ }
1448
+ }
1449
+ } else if (classes[r].depth > classes[l].depth) {
1450
+ int id = ~(classes[r].parent);
1451
+ for (int i = classes[l].depth + 1; i < classes[r].depth; ++i) {
1452
+ id = nodes[id].left;
1453
+ }
1454
+ while (id >= 0 && nodes[id].size == cmax) {
1455
+ int new_id = newNode();
1456
+ int left_id = nodes[id].left;
1457
+
1458
+ popLeft(id);
1459
+ if (nodes[id].prio == nodes[left_id].prio) {
1460
+ setPrio(id);
1461
+ }
1462
+ push(new_id, left_id);
1463
+ pushLeft(new_id, ~(classes[l].parent));
1464
+
1465
+ if (less(~classes[l].parent, left_id)) {
1466
+ nodes[new_id].item = nodes[~classes[l].parent].item;
1467
+ nodes[new_id].prio = nodes[~classes[l].parent].prio;
1468
+ } else {
1469
+ nodes[new_id].item = nodes[left_id].item;
1470
+ nodes[new_id].prio = nodes[left_id].prio;
1471
+ }
1472
+
1473
+ id = nodes[id].parent;
1474
+ classes[l].parent = ~new_id;
1475
+
1476
+ }
1477
+ if (id < 0) {
1478
+ int new_parent = newNode();
1479
+ nodes[new_parent].next = -1;
1480
+ nodes[new_parent].prev = -1;
1481
+ nodes[new_parent].parent = ~l;
1482
+
1483
+ push(new_parent, ~(classes[r].parent));
1484
+ pushLeft(new_parent, ~(classes[l].parent));
1485
+ setPrio(new_parent);
1486
+
1487
+ classes[r].parent = ~new_parent;
1488
+ classes[r].depth += 1;
1489
+ } else {
1490
+ pushLeft(id, ~(classes[l].parent));
1491
+ while (id >= 0 && less(~(classes[l].parent), id)) {
1492
+ nodes[id].prio = nodes[~(classes[l].parent)].prio;
1493
+ nodes[id].item = nodes[~(classes[l].parent)].item;
1494
+ id = nodes[id].parent;
1495
+ }
1496
+ }
1497
+ nodes[~(classes[r].parent)].parent = ~l;
1498
+ classes[l].parent = classes[r].parent;
1499
+ classes[l].depth = classes[r].depth;
1500
+ } else {
1501
+ if (classes[l].depth != 0 &&
1502
+ nodes[~(classes[l].parent)].size +
1503
+ nodes[~(classes[r].parent)].size <= cmax) {
1504
+ splice(~(classes[l].parent), ~(classes[r].parent));
1505
+ deleteNode(~(classes[r].parent));
1506
+ if (less(~(classes[r].parent), ~(classes[l].parent))) {
1507
+ nodes[~(classes[l].parent)].prio =
1508
+ nodes[~(classes[r].parent)].prio;
1509
+ nodes[~(classes[l].parent)].item =
1510
+ nodes[~(classes[r].parent)].item;
1511
+ }
1512
+ } else {
1513
+ int new_parent = newNode();
1514
+ nodes[new_parent].next = nodes[new_parent].prev = -1;
1515
+ push(new_parent, ~(classes[l].parent));
1516
+ pushRight(new_parent, ~(classes[r].parent));
1517
+ setPrio(new_parent);
1518
+
1519
+ classes[l].parent = ~new_parent;
1520
+ classes[l].depth += 1;
1521
+ nodes[new_parent].parent = ~l;
1522
+ }
1523
+ }
1524
+ if (classes[r].next != -1) {
1525
+ classes[classes[r].next].prev = classes[r].prev;
1526
+ }
1527
+ classes[classes[r].prev].next = classes[r].next;
1528
+
1529
+ classes[r].prev = classes[l].right;
1530
+ classes[classes[l].right].next = r;
1531
+ classes[l].right = r;
1532
+ classes[r].parent = l;
1533
+
1534
+ classes[r].next = -1;
1535
+ classes[r].depth = rln;
1536
+ }
1537
+ }
1538
+ return class_id;
1539
+ }
1540
+
1541
+ /// \brief Split the class to subclasses.
1542
+ ///
1543
+ /// The current function splits the given class. The join, which
1544
+ /// made the current class, stored a reference to the
1545
+ /// subclasses. The \c splitClass() member restores the classes
1546
+ /// and creates the heaps. The parameter is an STL output iterator
1547
+ /// which will be filled with the subclass ids. The time
1548
+ /// complexity is O(log(n)*k) where n is the overall number of
1549
+ /// nodes in the splitted classes and k is the number of the
1550
+ /// classes.
1551
+ template <typename Iterator>
1552
+ void split(int cls, Iterator out) {
1553
+ std::vector<int> cs;
1554
+ { // splitting union-find
1555
+ int id = cls;
1556
+ int l = classes[id].left;
1557
+
1558
+ classes[l].parent = classes[id].parent;
1559
+ classes[l].depth = classes[id].depth;
1560
+
1561
+ nodes[~(classes[l].parent)].parent = ~l;
1562
+
1563
+ *out++ = l;
1564
+
1565
+ while (l != -1) {
1566
+ cs.push_back(l);
1567
+ l = classes[l].next;
1568
+ }
1569
+
1570
+ classes[classes[id].right].next = first_class;
1571
+ classes[first_class].prev = classes[id].right;
1572
+ first_class = classes[id].left;
1573
+
1574
+ if (classes[id].next != -1) {
1575
+ classes[classes[id].next].prev = classes[id].prev;
1576
+ }
1577
+ classes[classes[id].prev].next = classes[id].next;
1578
+
1579
+ deleteClass(id);
1580
+ }
1581
+
1582
+ {
1583
+ for (int i = 1; i < int(cs.size()); ++i) {
1584
+ int l = classes[cs[i]].depth;
1585
+ while (nodes[nodes[l].parent].left == l) {
1586
+ l = nodes[l].parent;
1587
+ }
1588
+ int r = l;
1589
+ while (nodes[l].parent >= 0) {
1590
+ l = nodes[l].parent;
1591
+ int new_node = newNode();
1592
+
1593
+ nodes[new_node].prev = -1;
1594
+ nodes[new_node].next = -1;
1595
+
1596
+ split(r, new_node);
1597
+ pushAfter(l, new_node);
1598
+ setPrio(l);
1599
+ setPrio(new_node);
1600
+ r = new_node;
1601
+ }
1602
+ classes[cs[i]].parent = ~r;
1603
+ classes[cs[i]].depth = classes[~(nodes[l].parent)].depth;
1604
+ nodes[r].parent = ~cs[i];
1605
+
1606
+ nodes[l].next = -1;
1607
+ nodes[r].prev = -1;
1608
+
1609
+ repairRight(~(nodes[l].parent));
1610
+ repairLeft(cs[i]);
1611
+
1612
+ *out++ = cs[i];
1613
+ }
1614
+ }
1615
+ }
1616
+
1617
+ /// \brief Gives back the priority of the current item.
1618
+ ///
1619
+ /// Gives back the priority of the current item.
1620
+ const Value& operator[](const Item& item) const {
1621
+ return nodes[index[item]].prio;
1622
+ }
1623
+
1624
+ /// \brief Sets the priority of the current item.
1625
+ ///
1626
+ /// Sets the priority of the current item.
1627
+ void set(const Item& item, const Value& prio) {
1628
+ if (comp(prio, nodes[index[item]].prio)) {
1629
+ decrease(item, prio);
1630
+ } else if (!comp(prio, nodes[index[item]].prio)) {
1631
+ increase(item, prio);
1632
+ }
1633
+ }
1634
+
1635
+ /// \brief Increase the priority of the current item.
1636
+ ///
1637
+ /// Increase the priority of the current item.
1638
+ void increase(const Item& item, const Value& prio) {
1639
+ int id = index[item];
1640
+ int kd = nodes[id].parent;
1641
+ nodes[id].prio = prio;
1642
+ while (kd >= 0 && nodes[kd].item == item) {
1643
+ setPrio(kd);
1644
+ kd = nodes[kd].parent;
1645
+ }
1646
+ }
1647
+
1648
+ /// \brief Increase the priority of the current item.
1649
+ ///
1650
+ /// Increase the priority of the current item.
1651
+ void decrease(const Item& item, const Value& prio) {
1652
+ int id = index[item];
1653
+ int kd = nodes[id].parent;
1654
+ nodes[id].prio = prio;
1655
+ while (kd >= 0 && less(id, kd)) {
1656
+ nodes[kd].prio = prio;
1657
+ nodes[kd].item = item;
1658
+ kd = nodes[kd].parent;
1659
+ }
1660
+ }
1661
+
1662
+ /// \brief Gives back the minimum priority of the class.
1663
+ ///
1664
+ /// Gives back the minimum priority of the class.
1665
+ const Value& classPrio(int cls) const {
1666
+ return nodes[~(classes[cls].parent)].prio;
1667
+ }
1668
+
1669
+ /// \brief Gives back the minimum priority item of the class.
1670
+ ///
1671
+ /// \return Gives back the minimum priority item of the class.
1672
+ const Item& classTop(int cls) const {
1673
+ return nodes[~(classes[cls].parent)].item;
1674
+ }
1675
+
1676
+ /// \brief Gives back a representant item of the class.
1677
+ ///
1678
+ /// Gives back a representant item of the class.
1679
+ /// The representant is indpendent from the priorities of the
1680
+ /// items.
1681
+ const Item& classRep(int id) const {
1682
+ int parent = classes[id].parent;
1683
+ return nodes[parent >= 0 ? classes[id].depth : leftNode(id)].item;
1684
+ }
1685
+
1686
+ /// \brief LEMON style iterator for the items of a class.
1687
+ ///
1688
+ /// ClassIt is a lemon style iterator for the components. It iterates
1689
+ /// on the items of a class. By example if you want to iterate on
1690
+ /// each items of each classes then you may write the next code.
1691
+ ///\code
1692
+ /// for (ClassIt cit(huf); cit != INVALID; ++cit) {
1693
+ /// std::cout << "Class: ";
1694
+ /// for (ItemIt iit(huf, cit); iit != INVALID; ++iit) {
1695
+ /// std::cout << toString(iit) << ' ' << std::endl;
1696
+ /// }
1697
+ /// std::cout << std::endl;
1698
+ /// }
1699
+ ///\endcode
1700
+ class ItemIt {
1701
+ private:
1702
+
1703
+ const HeapUnionFind* _huf;
1704
+ int _id, _lid;
1705
+
1706
+ public:
1707
+
1708
+ /// \brief Default constructor
1709
+ ///
1710
+ /// Default constructor
1711
+ ItemIt() {}
1712
+
1713
+ ItemIt(const HeapUnionFind& huf, int cls) : _huf(&huf) {
1714
+ int id = cls;
1715
+ int parent = _huf->classes[id].parent;
1716
+ if (parent >= 0) {
1717
+ _id = _huf->classes[id].depth;
1718
+ if (_huf->classes[id].next != -1) {
1719
+ _lid = _huf->classes[_huf->classes[id].next].depth;
1720
+ } else {
1721
+ _lid = -1;
1722
+ }
1723
+ } else {
1724
+ _id = _huf->leftNode(id);
1725
+ _lid = -1;
1726
+ }
1727
+ }
1728
+
1729
+ /// \brief Increment operator
1730
+ ///
1731
+ /// It steps to the next item in the class.
1732
+ ItemIt& operator++() {
1733
+ _id = _huf->nextNode(_id);
1734
+ return *this;
1735
+ }
1736
+
1737
+ /// \brief Conversion operator
1738
+ ///
1739
+ /// It converts the iterator to the current item.
1740
+ operator const Item&() const {
1741
+ return _huf->nodes[_id].item;
1742
+ }
1743
+
1744
+ /// \brief Equality operator
1745
+ ///
1746
+ /// Equality operator
1747
+ bool operator==(const ItemIt& i) {
1748
+ return i._id == _id;
1749
+ }
1750
+
1751
+ /// \brief Inequality operator
1752
+ ///
1753
+ /// Inequality operator
1754
+ bool operator!=(const ItemIt& i) {
1755
+ return i._id != _id;
1756
+ }
1757
+
1758
+ /// \brief Equality operator
1759
+ ///
1760
+ /// Equality operator
1761
+ bool operator==(Invalid) {
1762
+ return _id == _lid;
1763
+ }
1764
+
1765
+ /// \brief Inequality operator
1766
+ ///
1767
+ /// Inequality operator
1768
+ bool operator!=(Invalid) {
1769
+ return _id != _lid;
1770
+ }
1771
+
1772
+ };
1773
+
1774
+ /// \brief Class iterator
1775
+ ///
1776
+ /// The iterator stores
1777
+ class ClassIt {
1778
+ private:
1779
+
1780
+ const HeapUnionFind* _huf;
1781
+ int _id;
1782
+
1783
+ public:
1784
+
1785
+ ClassIt(const HeapUnionFind& huf)
1786
+ : _huf(&huf), _id(huf.first_class) {}
1787
+
1788
+ ClassIt(const HeapUnionFind& huf, int cls)
1789
+ : _huf(&huf), _id(huf.classes[cls].left) {}
1790
+
1791
+ ClassIt(Invalid) : _huf(0), _id(-1) {}
1792
+
1793
+ const ClassIt& operator++() {
1794
+ _id = _huf->classes[_id].next;
1795
+ return *this;
1796
+ }
1797
+
1798
+ /// \brief Equality operator
1799
+ ///
1800
+ /// Equality operator
1801
+ bool operator==(const ClassIt& i) {
1802
+ return i._id == _id;
1803
+ }
1804
+
1805
+ /// \brief Inequality operator
1806
+ ///
1807
+ /// Inequality operator
1808
+ bool operator!=(const ClassIt& i) {
1809
+ return i._id != _id;
1810
+ }
1811
+
1812
+ operator int() const {
1813
+ return _id;
1814
+ }
1815
+
1816
+ };
1817
+
1818
+ };
1819
+
1820
+ //! @}
1821
+
1822
+ } //namespace lemon
1823
+
1824
+ #endif //LEMON_UNION_FIND_H