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/queue_array.hpp>
58#include <lal/detail/graphs/traversal.hpp>
59#include <lal/detail/type_traits/conditional_list.hpp>
126 std::enable_if_t<std::is_base_of_v<graphs::tree, tree_t>,
bool> =
true
138 std::pair<node, node>,
139 std::pair<std::pair<node, node>, array<uint64_t>>,
140 std::pair<std::pair<node, node>, array<edge_size>>
145 const auto n = t.get_num_nodes();
146 const auto size_cc_x = t.get_num_nodes_component(x);
148 if (size_cc_x == 1) {
149 if constexpr (
is_m1(mode)) {
152 else if constexpr (
is_m2(mode)) {
155 else if constexpr (
is_m3(mode)) {
158 return {{x,2}, std::move(s)};
160 else if constexpr (
is_m4(mode)) {
164 if (size_cc_x == 2) {
165 auto only_neigh = [&]() {
166 if constexpr (std::is_base_of_v<graphs::free_tree, tree_t>) {
167 return t.get_neighbors(x)[0];
170 if (t.get_out_degree(x) == 0) {
return t.get_in_neighbors(x)[0]; }
171 else {
return t.get_out_neighbors(x)[0]; }
175 const node u = (x < only_neigh ? x : only_neigh);
176 const node v =
is_m1(mode) ? 0 : (x < only_neigh ? only_neigh : x);
178 if constexpr (
is_m1(mode)) {
181 else if constexpr (
is_m2(mode)) {
184 else if constexpr (
is_m3(mode)) {
188 return {{u, v}, std::move(s)};
190 else if constexpr (
is_m4(mode)) {
198 const auto ndiv2 = size_cc_x/2 + size_cc_x%2;
210 std::size_t idx_edge_sizes = 0;
211 if constexpr (
is_m4(mode)) {
212 edge_sizes.
resize(size_cc_x - 1);
217 queue.
init(size_cc_x);
220 if (size_cc_x < n/2) {
222 bfs.set_use_rev_edges(std::is_base_of_v<graphs::rooted_tree, tree_t>);
223 bfs.set_process_current(
224 [&](
const auto&,
const node u) {
225 degree[u] = t.get_degree(u);
227 if (t.get_degree(u) == 1) {
235 for (
node u = 0; u < n; ++u) {
236 if (t.get_component_representative(u) == t.get_component_representative(x)) {
237 degree[u] = t.get_degree(u);
238 if (t.get_degree(u) == 1) {
246 while (queue.
size() > 0) {
250 if (weight[u] >= ndiv2) {
251 if (c1 >= size_cc_x) {
254 if constexpr (
is_m1(mode)) {
return u; }
267 assert(degree[u] == 0);
271 if constexpr (std::is_base_of_v<graphs::free_tree, tree_t>) {
272 for (
const node v : t.get_neighbors(u)) {
273 if (degree[v] == 0) {
continue; }
276 weight[v] += weight[u];
277 if (degree[v] == 1) {
281 if constexpr (
is_m4(mode)) {
282 edge_sizes[idx_edge_sizes++] = {{v,u}, weight[u]};
287 for (
const node v : t.get_in_neighbors(u)) {
288 if (degree[v] == 0) {
continue; }
291 weight[v] += weight[u];
292 if (degree[v] == 1) {
296 if constexpr (
is_m4(mode)) {
297 edge_sizes[idx_edge_sizes++] = {{v,u}, weight[u]};
300 for (
const node v : t.get_out_neighbors(u)) {
301 if (degree[v] == 0) {
continue; }
304 weight[v] += weight[u];
305 if (degree[v] == 1) {
309 if constexpr (
is_m4(mode)) {
310 edge_sizes[idx_edge_sizes++] = {{v,u}, weight[u]};
320 weight[c1] += weight[c2];
322 if constexpr (
is_m4(mode)) {
323 edge_sizes[idx_edge_sizes++] = {{c1,c2}, weight[c2]};
328 if constexpr (
is_m4(mode)) {
329 assert(idx_edge_sizes == edge_sizes.
size());
333 if constexpr (
is_m2(mode)) {
336 else if constexpr (
is_m3(mode)) {
337 return {{c1, c2}, std::move(weight)};
339 else if constexpr (
is_m4(mode)) {
340 return {{c1, c2}, std::move(edge_sizes)};
357 std::enable_if_t<std::is_base_of_v<graphs::tree, tree_t>,
bool> =
true
363 std::vector< std::vector<node_size> >& L
369 centroid_subtree_sizes =
372 const uint64_t n = t.get_num_nodes();
378 centroid_subtree_sizes.second.begin(),
379 centroid_subtree_sizes.second.end(),
381 centroid_subtree_sizes.second.size(),
388 for (
const auto& [uv, suv] : centroid_subtree_sizes.second) {
389 const auto [u, v] = uv;
390 L[u].push_back({v, suv});
393 return centroid_subtree_sizes.first;
413 std::enable_if_t< std::is_base_of_v<graphs::tree, tree_t>,
bool > =
true
416(
const tree_t& t,
const node x = 0)
Abstract graph Breadth-First Search traversal.
Definition traversal.hpp:89
Simple array-like fixed-size queue.
Definition queue_array.hpp:69
void init(const std::size_t n) noexcept
Initializes the queue to hold n elements.
Definition queue_array.hpp:72
std::size_t size() const noexcept
Returns the size of the queue.
Definition queue_array.hpp:121
value_t && pop() noexcept
Pops the first element of the queue.
Definition queue_array.hpp:98
void push(const value_t &v) noexcept
Insert a new element to the queue.
Definition queue_array.hpp:79
@ non_increasing
Non-increasing sort.
void counting_sort(const value_iterator_t begin, const value_iterator_t end, const std::size_t largest_key_plus_1, const Callable &key, countingsort::memory< value_t > &mem) noexcept
Counting sort algorithm with reusable memory.
Definition counting_sort.hpp:152
constexpr bool is_m1(const centroid_results &m) noexcept
Is mode m equal to lal::detail::centroid_results::only_one_centroidal.
Definition tree_centroid.hpp:81
std::pair< node, node > retrieve_centroid(const tree_t &t, const node x=0) noexcept
Calculate the centroid of the connected component that has node x.
Definition tree_centroid.hpp:416
constexpr bool is_m3(const centroid_results &m) noexcept
Is mode m equal to lal::detail::centroid_results::full_centroid_plus_subtree_sizes.
Definition tree_centroid.hpp:89
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.
constexpr bool is_m2(const centroid_results &m) noexcept
Is mode m equal to lal::detail::centroid_results::full_centroid.
Definition tree_centroid.hpp:85
typename conditional_list< bool_seq, type_seq >::type conditional_list_t
Shorthand for conditional_list.
Definition conditional_list.hpp:78
std::pair< node, node > centroidal_vertex_plus_adjacency_list(const tree_t &t, const node x, std::vector< std::vector< node_size > > &L) noexcept
Calculates the centroid and the corresponding rooted adjacency list.
Definition tree_centroid.hpp:360
constexpr bool is_m4(const centroid_results &m) noexcept
Is mode m equal to lal::detail::centroid_results::full_centroid_plus_edge_sizes.
Definition tree_centroid.hpp:93
conditional_list_t< bool_sequence< is_m1(mode), is_m2(mode), is_m3(mode), is_m4(mode) >, type_sequence< node, std::pair< node, node >, std::pair< std::pair< node, node >, array< uint64_t > >, std::pair< std::pair< node, node >, array< edge_size > > > > find_centroidal_vertex(const tree_t &t, const node x) noexcept
Calculates the centroid of a tree.
Definition tree_centroid.hpp:143
Main namespace of the library.
Definition basic_types.hpp:48
std::pair< edge, edge > edge_pair
Edge pair type.
Definition basic_types.hpp:62
uint64_t node
Node type. See Node / Vertex page for further details.
Definition basic_types.hpp:51
Wrapper of a C array for automatic deallocation of memory.
Definition array.hpp:59
std::size_t size() const noexcept
Size of the array.
Definition array.hpp:215
void resize(const std::size_t new_size) noexcept
Resize the array.
Definition array.hpp:187
Struct used in many algorithms to sort edges according to some integer value.
Definition pairs_utils.hpp:65