51#include <lal/graphs/output.hpp>
52#include <lal/basic_types.hpp>
53#include <lal/graphs/rooted_tree.hpp>
54#include <lal/detail/graphs/size_subtrees.hpp>
55#include <lal/detail/sorting/counting_sort.hpp>
56#include <lal/detail/pairs_utils.hpp>
57#include <lal/detail/linear_queue.hpp>
58#include <lal/detail/graphs/traversal.hpp>
59#include <lal/detail/type_traits/conditional_list.hpp>
80#define m1(mode) (mode == centroid_results::only_one_centroidal)
81#define m2(mode) (mode == centroid_results::full_centroid)
82#define m3(mode) (mode == centroid_results::full_centroid_plus_subtree_sizes)
83#define m4(mode) (mode == centroid_results::full_centroid_plus_edge_sizes)
84#define node_pair std::pair<lal::node,lal::node>
116 std::enable_if_t<std::is_base_of_v<graphs::tree, tree_t>,
bool> =
true
127 std::pair<lal::node,lal::node>,
128 std::pair<std::pair<lal::node,lal::node>, data_array<uint64_t>>,
129 std::pair<std::pair<lal::node,lal::node>, data_array<edge_size>>
134 const auto N = t.get_num_nodes();
135 const auto n = t.get_num_nodes_component(x);
138 if constexpr (m1(mode)) {
141 else if constexpr (m2(mode)) {
144 else if constexpr (m3(mode)) {
147 return {{x,2}, std::move(s)};
149 else if constexpr (m4(mode)) {
154 auto only_neigh = [&]() {
155 if constexpr (std::is_base_of_v<graphs::free_tree, tree_t>) {
156 return t.get_neighbours(x)[0];
159 if (t.get_out_degree(x) == 0) {
return t.get_in_neighbours(x)[0]; }
160 else {
return t.get_out_neighbours(x)[0]; }
164 if (x > only_neigh) { std::swap(x, only_neigh); }
165 if constexpr (m1(mode)) {
168 else if constexpr (m2(mode)) {
169 return {x,only_neigh};
171 else if constexpr (m3(mode)) {
175 return {{x,only_neigh}, std::move(s)};
177 else if constexpr (m4(mode)) {
185 const auto ndiv2 = n/2 + n%2;
197 std::size_t idx_edge_sizes = 0;
198 if constexpr (m4(mode)) {
211 [&](
const auto&,
node u) {
212 degree[u] = t.get_degree(u);
214 if (t.get_degree(u) == 1) {
223 while (queue.
size() > 0) {
227 if (weight[u] >= ndiv2) {
231 if constexpr (m1(mode)) {
return u; }
244 assert(degree[u] == 0);
248 if constexpr (std::is_base_of_v<graphs::free_tree, tree_t>) {
249 for (
node v : t.get_neighbours(u)) {
250 if (degree[v] == 0) {
continue; }
253 weight[v] += weight[u];
254 if (degree[v] == 1) {
258 if constexpr (m4(mode)) {
259 edge_sizes[idx_edge_sizes++] = {{v,u}, weight[u]};
264 for (
node v : t.get_in_neighbours(u)) {
265 if (degree[v] == 0) {
continue; }
268 weight[v] += weight[u];
269 if (degree[v] == 1) {
273 if constexpr (m4(mode)) {
274 edge_sizes[idx_edge_sizes++] = {{v,u}, weight[u]};
277 for (
node v : t.get_out_neighbours(u)) {
278 if (degree[v] == 0) {
continue; }
281 weight[v] += weight[u];
282 if (degree[v] == 1) {
286 if constexpr (m4(mode)) {
287 edge_sizes[idx_edge_sizes++] = {{v,u}, weight[u]};
297 weight[c1] += weight[c2];
299 if constexpr (m4(mode)) {
300 edge_sizes[idx_edge_sizes++] = {{c1,c2}, weight[c2]};
305 if constexpr (m4(mode)) {
306 assert(idx_edge_sizes == edge_sizes.
size());
310 if constexpr (m2(mode)) {
313 else if constexpr (m3(mode)) {
314 return {{c1, c2}, std::move(weight)};
316 else if constexpr (m4(mode)) {
317 return {{c1, c2}, std::move(edge_sizes)};
341 std::enable_if_t<std::is_base_of_v<graphs::tree, tree_t>,
bool> =
true
344 const tree_t& t,
node x,
345 std::vector< std::vector<node_size> >& L
351 centroid_subtree_sizes =
352 find_centroidal_vertex<centroid_results::full_centroid_plus_edge_sizes>(t, x);
354 auto sizes_edge = std::move(centroid_subtree_sizes.second);
356 const uint64_t n = t.get_num_nodes();
362 sizes_edge.begin(), sizes_edge.end(), n, sizes_edge.size(),
369 for (
const auto& [uv, suv] : sizes_edge) {
370 const auto [u, v] = uv;
371 L[u].push_back({v, suv});
374 return centroid_subtree_sizes.first;
394 std::enable_if_t< std::is_base_of_v<graphs::tree, tree_t>,
bool > =
true
399 return find_centroidal_vertex<centroid_results::full_centroid>(t, x);
417 std::enable_if_t< std::is_base_of_v<graphs::tree, tree_t>,
bool > =
true
422 return find_centroidal_vertex<centroid_results::full_centroid>(t, 0);
Abstract graph Breadth-First Search traversal.
Definition: traversal.hpp:89
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
Simple array-like fixed-size queue.
Definition: linear_queue.hpp:69
T && pop() noexcept
Pops the first element of the queue.
Definition: linear_queue.hpp:98
std::size_t size() const noexcept
Returns the size of the queue.
Definition: linear_queue.hpp:121
void push(const T &v) noexcept
Insert a new element to the queue.
Definition: linear_queue.hpp:79
void init(std::size_t n) noexcept
Initializes the queue to hold n elements.
Definition: linear_queue.hpp:72
void counting_sort(const value_iterator_t begin, const value_iterator_t end, const std::size_t largest_key_plus_1, const std::function< std::size_t(const value_t &)> &key, countingsort::memory< value_t > &mem) noexcept
Counting sort algorithm with reusable memory.
Definition: counting_sort.hpp:155
std::pair< node, node > retrieve_centroid(const tree_t &t, const node x) noexcept
Calculate the centroid of the connected component that has node x.
Definition: tree_centroid.hpp:396
centroid_results
The different types of results.
Definition: tree_centroid.hpp:65
@ full_centroid_plus_edge_sizes
Returns the full centroid of the tree. Also returns the edge_size array.
@ full_centroid
Returns the full centroid of the tree. No weights.
@ only_one_centroidal
Returns only one centroidal vertex. No weights.
@ full_centroid_plus_subtree_sizes
Returns the full centroid of the tree. Also returns the weights.
conditional_list_t< bool_sequence< m1(mode), m2(mode), m3(mode), m4(mode) >, type_sequence< node, std::pair< lal::node, lal::node >, std::pair< std::pair< lal::node, lal::node >, data_array< uint64_t > >, std::pair< std::pair< lal::node, lal::node >, data_array< edge_size > > > > find_centroidal_vertex(const tree_t &t, node x) noexcept
Calculates the centroid of a tree.
Definition: tree_centroid.hpp:132
std::pair< node, node > centroidal_vertex_plus_adjacency_list(const tree_t &t, node x, std::vector< std::vector< node_size > > &L) noexcept
Calculates the centroid and the corresponding rooted adjacency list.
Definition: tree_centroid.hpp:343
typename conditional_list< bool_seq, type_seq >::type conditional_list_t
Shorthand for conditional_list.
Definition: conditional_list.hpp:78
Main namespace of the library.
Definition: basic_types.hpp:50
std::pair< edge, edge > edge_pair
Edge pair type.
Definition: basic_types.hpp:60
uint64_t node
Node type. See Node / Vertex page for further details.
Definition: basic_types.hpp:53
Wrapper of a C array for autmatic deallocation of memory.
Definition: data_array.hpp:59
std::size_t size() const noexcept
Size of the array.
Definition: data_array.hpp:204
void resize(std::size_t new_size) noexcept
Resize the array.
Definition: data_array.hpp:175
Struct used in many algorithms to sort edges according to some integer value.
Definition: pairs_utils.hpp:65
Non-increasing sort.
Definition: sorting_types.hpp:51