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.
- checksums.yaml +7 -0
- data/.yardopts +8 -0
- data/LICENSE +674 -0
- data/README.md +6 -0
- data/ext/lemon-1.3.1/AUTHORS +26 -0
- data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
- data/ext/lemon-1.3.1/INSTALL +167 -0
- data/ext/lemon-1.3.1/LICENSE +32 -0
- data/ext/lemon-1.3.1/NEWS +337 -0
- data/ext/lemon-1.3.1/README +50 -0
- data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
- data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
- data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
- data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
- data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
- data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
- data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
- data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
- data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
- data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
- data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
- data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
- data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
- data/ext/lemon-1.3.1/lemon/assert.h +214 -0
- data/ext/lemon-1.3.1/lemon/base.cc +37 -0
- data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
- data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
- data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
- data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
- data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
- data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
- data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
- data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
- data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
- data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
- data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
- data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
- data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
- data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
- data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
- data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
- data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
- data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
- data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
- data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
- data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
- data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
- data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
- data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
- data/ext/lemon-1.3.1/lemon/clp.h +164 -0
- data/ext/lemon-1.3.1/lemon/color.cc +44 -0
- data/ext/lemon-1.3.1/lemon/color.h +204 -0
- data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
- data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
- data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
- data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
- data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
- data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
- data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
- data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
- data/ext/lemon-1.3.1/lemon/core.h +2506 -0
- data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
- data/ext/lemon-1.3.1/lemon/counter.h +249 -0
- data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
- data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
- data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
- data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
- data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
- data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
- data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
- data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
- data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
- data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
- data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
- data/ext/lemon-1.3.1/lemon/error.h +276 -0
- data/ext/lemon-1.3.1/lemon/euler.h +287 -0
- data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
- data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
- data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
- data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
- data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
- data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
- data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
- data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
- data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
- data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
- data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
- data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
- data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
- data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
- data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
- data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
- data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
- data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
- data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
- data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
- data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
- data/ext/lemon-1.3.1/lemon/lp.h +95 -0
- data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
- data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
- data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
- data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
- data/ext/lemon-1.3.1/lemon/math.h +77 -0
- data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
- data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
- data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
- data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
- data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
- data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
- data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
- data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
- data/ext/lemon-1.3.1/lemon/path.h +1164 -0
- data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
- data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
- data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
- data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
- data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
- data/ext/lemon-1.3.1/lemon/random.cc +29 -0
- data/ext/lemon-1.3.1/lemon/random.h +1005 -0
- data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
- data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
- data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
- data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
- data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
- data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
- data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
- data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
- data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
- data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
- data/ext/lemongraph/arc_map.cc +1007 -0
- data/ext/lemongraph/digraph.cc +282 -0
- data/ext/lemongraph/digraph_arc.cc +153 -0
- data/ext/lemongraph/digraph_node.cc +277 -0
- data/ext/lemongraph/edge_map.cc +770 -0
- data/ext/lemongraph/extconf.rb +53 -0
- data/ext/lemongraph/graph.cc +351 -0
- data/ext/lemongraph/graph_arc.cc +95 -0
- data/ext/lemongraph/graph_edge.cc +153 -0
- data/ext/lemongraph/graph_item.cc +76 -0
- data/ext/lemongraph/graph_node.cc +321 -0
- data/ext/lemongraph/lemongraph.cc +260 -0
- data/ext/lemongraph/lemongraph.hh +295 -0
- data/ext/lemongraph/lemongraph.map +6 -0
- data/ext/lemongraph/lemongraph_export.hh +31 -0
- data/ext/lemongraph/node_map.cc +1011 -0
- data/lemongraph.gemspec +176 -0
- data/lib/lemongraph/graphviz.rb +240 -0
- data/lib/lemongraph/version.rb +4 -0
- data/lib/lemongraph.rb +21 -0
- data/samples/lemondeps.rb +38 -0
- 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
|