LAL: Linear Arrangement Library 23.01.00
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 - 2023
7 *
8 * This file is part of Linear Arrangement Library. The full code is available
9 * at:
10 * https://github.com/LAL-project/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/basic_types.hpp>
51#include <lal/graphs/rooted_tree.hpp>
52#include <lal/graphs/free_tree.hpp>
53#include <lal/detail/graphs/traversal.hpp>
54
55namespace lal {
56namespace detail {
57
72template <class tree_t>
74(
75 const tree_t& t, const node u, const node v,
76 node * const root_of,
77 uint64_t * const root_size
78)
79noexcept
80{
81 // 'u' and 'v' are not connected, so they belong to
82 // (different) connected components of the tree.
83
84 // 'parent' and 'child' determine a direction to be used later.
85 // 'new_root' is the new root for one of the vertices
86 node parent, child, new_root;
87
88 const node root_u = root_of[u];
89 const node root_v = root_of[v];
90
91 const uint64_t size_u = root_size[root_u];
92 const uint64_t size_v = root_size[root_v];
93 const uint64_t new_size = size_u + size_v;
94
95 if (size_u < size_v) {
96 root_of[root_u] = root_v;
97 root_of[u] = root_v;
98
99 new_root = root_v;
100 root_size[new_root] = new_size;
101
102 // update roots in the direction of v -> u
103 parent = v; child = u;
104 }
105 else {
106 root_of[root_v] = root_u;
107 root_of[v] = root_u;
108
109 new_root = root_u;
110 root_size[new_root] = new_size;
111
112 // update roots in the direction of u -> v
113 parent = u; child = v;
114 }
115
116 // update roots of the smaller component,
117 // in the direction parent -> child
118 BFS<tree_t> bfs(t);
121 [&](const BFS<tree_t>&, node w) -> void { root_of[w] = new_root; }
122 );
123 bfs.set_visited(parent, 1); // avoid going backwards
124 bfs.start_at(child);
125}
126
141template <class tree_t>
143(
144 const tree_t& t, const node u, const node v,
145 node * const root_of,
146 uint64_t * const root_size
147)
148noexcept
149{
150 // 'u' and 'v' are connected
151#if defined DEBUG
152 assert(root_of[u] == root_of[v]);
153#endif
154
155 const uint64_t size_uv = root_size[root_of[u]];
156
157 BFS<tree_t> bfs(t);
158
159 // --- update u's info ---
160
161 // Update the root of the vertices reachable from 'u'.
162 // (also calculate the size of u's component)
163 uint64_t size_cc_u = 0;
166 [&](const auto&, node w) -> void {
167 root_of[w] = u;
168 ++size_cc_u;
169 }
170 );
171 bfs.start_at(u);
172 root_of[u] = u;
173 root_size[u] = size_cc_u;
174
175 // --- update v's info ---
176
177 // Update the root of the vertices reachable from 'v'.
178 // (there is no need to reset the BFS object)
180 [&](const detail::BFS<tree_t>&, node w) -> void {
181 root_of[w] = v;
182 }
183 );
184 bfs.start_at(v);
185 root_of[v] = v;
186 root_size[v] = size_uv - size_cc_u;
187}
188
189// -----------------------------------------------------------------------------
190
209template <class tree_t>
211(
212 BFS<tree_t>& bfs, node v,
213 node * const root_of,
214 uint64_t * const root_size
215)
216noexcept
217{
218 uint64_t size_cc_v = 0;
219 bfs.set_process_current(
220 [&](const auto&, node w) -> void {
221 root_of[w] = v;
222 ++size_cc_v;
223 }
224 );
225 bfs.start_at(v);
226
227 root_of[v] = v;
228 root_size[v] = size_cc_v;
229}
230
249template <typename tree_t>
251(
252 const tree_t& t, node u,
253 node * const root_of,
254 uint64_t * const root_size
255)
256noexcept
257{
258 BFS<tree_t> bfs(t);
259 bfs.set_use_rev_edges(t.is_directed());
260 // avoid going 'backwards', we need to go 'onwards'
261 bfs.set_visited(u, 1);
262
263 if constexpr (std::is_base_of_v<graphs::free_tree, tree_t>) {
264 for (node v : t.get_neighbours(u)) {
265 // update size and root of the edges from v onwards
266 // (onwards means "in the direction u -> v"
268 (bfs, v, root_of, root_size);
269 }
270 }
271 else {
272 for (node v : t.get_in_neighbours(u)) {
273 // update size and root of the edges from v onwards
274 // (onwards means "in the direction u -> v"
276 (bfs, v, root_of, root_size);
277 }
278 for (node v : t.get_out_neighbours(u)) {
279 // update size and root of the edges from v onwards
280 // (onwards means "in the direction u -> v"
282 (bfs, v, root_of, root_size);
283 }
284 }
285
286 root_of[u] = u;
287 root_size[u] = 1;
288}
289
290} // -- namespace detail
291} // -- namespace lal
Abstract graph Breadth-First Search traversal.
Definition: traversal.hpp:89
void set_visited(node u, char vis) noexcept
Set node u as visited or not.
Definition: traversal.hpp:232
void set_process_current(const BFS_process_one &f) noexcept
Set the function that controls the processing of the current node.
Definition: traversal.hpp:186
void start_at(node source) noexcept
Start traversal at a given node.
Definition: traversal.hpp:152
void set_use_rev_edges(bool use) noexcept
Set whether the traversal can use reversed edges.
Definition: traversal.hpp:173
void update_unionfind_after_remove_edge(const tree_t &t, const node u, const node v, node *const root_of, uint64_t *const root_size) noexcept
Updates Union-Find after an edge removal.
Definition: union_find.hpp:143
void update_unionfind_before_remove_edges_incident_to(BFS< tree_t > &bfs, node v, node *const root_of, uint64_t *const root_size) noexcept
Update Union-Find after a vertex removal.
Definition: union_find.hpp:211
void update_unionfind_after_add_edge(const tree_t &t, const node u, const node v, node *const root_of, uint64_t *const root_size) noexcept
Update the Union-Find data structure after an edge addition to a tree.
Definition: union_find.hpp:74
Main namespace of the library.
Definition: basic_types.hpp:50
uint64_t node
Node type. See Node / Vertex page for further details.
Definition: basic_types.hpp:53