LAL: Linear Arrangement Library 21.07.01
A library focused on algorithms on linear arrangements of graphs.
Loading...
Searching...
No Matches
union_find.hpp
1/*********************************************************************
2 *
3 * Linear Arrangement Library - A library that implements a collection
4 * algorithms for linear arrangments of graphs.
5 *
6 * Copyright (C) 2019 - 2021
7 *
8 * This file is part of Linear Arrangement Library. To see the full code
9 * visit the webpage:
10 * https://github.com/lluisalemanypuig/linear-arrangement-library.git
11 *
12 * Linear Arrangement Library is free software: you can redistribute it
13 * and/or modify it under the terms of the GNU Affero General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * Linear Arrangement Library is distributed in the hope that it will be
18 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with Linear Arrangement Library. If not, see <http://www.gnu.org/licenses/>.
24 *
25 * Contact:
26 *
27 * LluĂ­s Alemany Puig (lalemany@cs.upc.edu)
28 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
29 * CQL (Complexity and Quantitative Linguistics Lab)
30 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
31 * Webpage: https://cqllab.upc.edu/people/lalemany/
32 *
33 * Ramon Ferrer i Cancho (rferrericancho@cs.upc.edu)
34 * LARCA (Laboratory for Relational Algorithmics, Complexity and Learning)
35 * CQL (Complexity and Quantitative Linguistics Lab)
36 * Office S124, Omega building
37 * Jordi Girona St 1-3, Campus Nord UPC, 08034 Barcelona. CATALONIA, SPAIN
38 * Webpage: https://cqllab.upc.edu/people/rferrericancho/
39 *
40 ********************************************************************/
41
42#pragma once
43
44// C++ includes
45#if defined DEBUG
46#include <cassert>
47#endif
48
49// lal includes
50#include <lal/definitions.hpp>
51#include <lal/graphs/rooted_tree.hpp>
52#include <lal/graphs/free_tree.hpp>
53#include <lal/internal/graphs/traversal.hpp>
54
55namespace lal {
56namespace internal {
57
58/* This function updates the union-find data structure of a tree after the
59 * addition of the edge between the edges 'u' and 'v'.
60 */
61template<typename T>
62void UnionFind_update_roots_after_add
63(
64 const T& t, node u, node v,
65 node * const root_of,
66 uint32_t * const root_size
67)
68{
69 // 'u' and 'v' are not connected, so they belong to
70 // (different) connected components of the tree.
71
72 // 'parent' and 'child' determine a direction to be used later.
73 // 'new_root' is the new root for one of the vertices
74 node parent, child, new_root;
75
76 const node root_u = root_of[u];
77 const node root_v = root_of[v];
78
79 const uint32_t size_u = root_size[root_u];
80 const uint32_t size_v = root_size[root_v];
81 const uint32_t new_size = size_u + size_v;
82
83 if (size_u < size_v) {
84 root_of[root_u] = root_v;
85 root_of[u] = root_v;
86
87 new_root = root_v;
88 root_size[new_root] = new_size;
89
90 // update roots in the direction of v -> u
91 parent = v; child = u;
92 }
93 else {
94 root_of[root_v] = root_u;
95 root_of[v] = root_u;
96
97 new_root = root_u;
98 root_size[new_root] = new_size;
99
100 // update roots in the direction of u -> v
101 parent = u; child = v;
102 }
103
104 // update roots of the smaller component,
105 // in the direction parent -> child
106 internal::BFS<T> bfs(t);
107 bfs.set_use_rev_edges(t.is_directed());
108 bfs.set_process_current(
109 [&](const auto&, node w) -> void { root_of[w] = new_root; }
110 );
111 bfs.set_visited(parent, 1); // avoid going backwards
112 bfs.start_at(child);
113}
114
115/* This function updates the union-find data structure of a tree after the
116 * removal of the edge between the edges 'u' and 'v'.
117 */
118template<typename T>
119void UnionFind_update_roots_after_remove
120(
121 const T& t, node u, node v,
122 node * const root_of,
123 uint32_t * const root_size
124)
125{
126 // 'u' and 'v' are connected
127#if defined DEBUG
128 assert(root_of[u] == root_of[v]);
129#endif
130
131 const uint32_t size_uv = root_size[root_of[u]];
132
133 internal::BFS<T> bfs(t);
134
135 // --- update u's info ---
136
137 // Update the root of the vertices reachable from 'u'.
138 // (also calculate the size of u's component)
139 uint32_t size_u = 0;
140 bfs.set_use_rev_edges(t.is_directed());
141 bfs.set_process_current(
142 [&](const auto&, node w) -> void { root_of[w] = u; ++size_u; }
143 );
144 bfs.start_at(u);
145 root_of[u] = u;
146 root_size[u] = size_u;
147
148 // --- update v's info ---
149
150 // Update the root of the vertices reachable from 'v'.
151 // (there is no need to reset the BFS object)
152 bfs.set_process_current(
153 [&](const auto&, node w) -> void { root_of[w] = v; }
154 );
155 bfs.start_at(v);
156 root_of[v] = v;
157 root_size[v] = size_uv - size_u;
158}
159
160// -----------------------------------------------------------------------------
161
162namespace __lal {
163
164/* This function updates the union-find data structure of a tree prior to the
165 * removal of the edge (u,v).
166 *
167 * This function is called by the function
168 * lal::internal::UnionFind_update_roots_before_remove_all_incident_to
169 *
170 * In particular, it updates the information associated to the vertices found
171 * in the direction (u,v).
172 */
173template<typename T>
174void UnionFind_update_roots_before_remove_all_incident_to
175(
176 const T& t, node u, node v,
177 node * const root_of,
178 uint32_t * const root_size
179)
180{
181 internal::BFS<T> bfs(t);
182 bfs.set_use_rev_edges(t.is_directed());
183 // avoid going 'backwards', we need to go 'onwards'
184 bfs.set_visited(u, 1);
185
186 uint32_t size_cc_v = 0;
187 bfs.set_process_current(
188 [&](const auto&, node w) -> void { root_of[w] = v; ++size_cc_v; }
189 );
190 bfs.start_at(v);
191
192 root_of[v] = v;
193 root_size[v] = size_cc_v;
194}
195
196} // -- namespace __lal
197
198/* This function updates the union-find data structure of a tree prior to the
199 * removal of the edges incidents to vertex 'u'.
200 */
201template<typename T>
202void UnionFind_update_roots_before_remove_all_incident_to
203(
204 const T& t, node u,
205 node * const root_of,
206 uint32_t * const root_size
207)
208{
209 if constexpr (std::is_base_of_v<graphs::free_tree, T>) {
210 for (node v : t.get_neighbours(u)) {
211 // update size and root of the edges from v onwards
212 // (onwards means "in the direction u -> v"
213 __lal::UnionFind_update_roots_before_remove_all_incident_to(
214 t, u, v, root_of, root_size
215 );
216 }
217 }
218 else {
219 for (node v : t.get_in_neighbours(u)) {
220 // update size and root of the edges from v onwards
221 // (onwards means "in the direction u -> v"
222 __lal::UnionFind_update_roots_before_remove_all_incident_to(
223 t, u, v, root_of, root_size
224 );
225 }
226 for (node v : t.get_out_neighbours(u)) {
227 // update size and root of the edges from v onwards
228 // (onwards means "in the direction u -> v"
229 __lal::UnionFind_update_roots_before_remove_all_incident_to(
230 t, u, v, root_of, root_size
231 );
232 }
233 }
234
235 root_of[u] = u;
236 root_size[u] = 1;
237}
238
239} // -- namespace internal
240} // -- namespace lal
Main namespace of the library.
Definition definitions.hpp:48
uint32_t node
Node type.
Definition definitions.hpp:51