37# include <gtest/gtest.h>
60 const std::vector<int> & values,
61 const std::vector<std::pair<size_t, size_t>> & edges)
66 for (
size_t i = 0; i < values.size(); ++i)
69 for (
const auto & [u, v] : edges)
75 std::vector<std::pair<size_t, size_t>>
78 std::vector<std::pair<size_t, size_t>> edges;
79 edges.reserve(n > 0 ? n - 1 : 0);
81 for (
size_t v = 1; v < n; ++v)
83 std::uniform_int_distribution<size_t> pick(0, v - 1);
84 edges.emplace_back(v, pick(
rng));
92 static constexpr size_t NONE = std::numeric_limits<size_t>::max();
97 std::vector<std::vector<size_t>> adj_;
98 std::vector<std::vector<size_t>> children_;
99 std::vector<size_t> parent_;
100 std::vector<size_t> depth_;
103 Rooted_Oracle(
const size_t n,
104 const std::vector<std::pair<size_t, size_t>> & edges,
113 for (
const auto & [u, v] : edges)
115 adj_[u].push_back(v);
116 adj_[v].push_back(u);
119 std::vector<char> visited(n_, 0);
127 std::vector<Frame> stack;
128 stack.push_back({root_, NONE, 0});
130 parent_[root_] = NONE;
133 while (
not stack.empty())
135 auto &
fr = stack.back();
136 if (
fr.next == adj_[
fr.u].size())
142 const size_t v = adj_[
fr.u][
fr.next++];
151 depth_[v] = depth_[
fr.u] + 1;
152 children_[
fr.u].push_back(v);
153 stack.push_back({v,
fr.u, 0});
157 [[
nodiscard]]
size_t lca(
size_t u,
size_t v)
const
159 while (depth_[u] > depth_[v])
162 while (depth_[v] > depth_[u])
174 [[
nodiscard]]
size_t distance(
const size_t u,
const size_t v)
const
176 const size_t a = lca(u, v);
177 return depth_[u] + depth_[v] - 2 * depth_[a];
186 while (depth_[u] > depth_[v])
192 while (depth_[v] > depth_[u])
211 const size_t u)
const
214 std::vector<size_t> stack;
217 while (
not stack.empty())
219 const size_t x = stack.back();
223 for (
const auto ch : children_[x])
232 class TreeDecompositionTypedTest :
public ::testing::Test
358 const std::vector<int> values = {5, 3, 4, 7, 2, 6, 1};
359 const std::vector<std::pair<size_t, size_t>> edges = {
360 {0, 1}, {0, 2}, {1, 3}, {1, 4}, {2, 5}, {5, 6}};
365 Rooted_Oracle
oracle(values.size(), edges, 0);
370 for (
size_t u = 0; u < values.size(); ++u)
371 for (
size_t v = 0; v < values.size(); ++v)
378 for (
size_t u = 0; u < values.size(); ++u)
380 const size_t id =
hld.id_of(
nodes(u));
381 const auto range =
hld.subtree_range_id(
id);
392 for (
size_t u = 0; u < values.size(); ++u)
393 for (
size_t v = 0; v < values.size(); ++v)
397 for (
size_t u = 0; u < values.size(); ++u)
405 std::mt19937
rng(0xA13F2026u);
406 std::uniform_int_distribution<int>
pick_value(-20, 20);
410 std::uniform_int_distribution<size_t>
pick_n(5, 60);
415 std::vector<int> values(n);
416 for (
size_t i = 0; i < n; ++i)
422 Rooted_Oracle
oracle(n, edges, 0);
426 std::uniform_int_distribution<size_t>
pick_id(0, n - 1);
428 for (
size_t it = 0; it < 250; ++it)
430 const int action =
static_cast<int>(
rng() % 100);
435 if ((
rng() & 1U) == 0
U)
467 const std::vector<int> values = {0, 1, 2, 3, 4, 5, 6, 7, 8};
468 const std::vector<std::pair<size_t, size_t>> edges = {
469 {0, 1}, {0, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}, {6, 7}, {6, 8}};
474 Rooted_Oracle
oracle(values.size(), edges, 0);
482 for (
size_t i = 0; i < values.size(); ++i)
489 for (
size_t u = 0; u < values.size(); ++u)
502 for (
size_t k = 0;
k < anc.size(); ++
k)
505 for (
size_t k = 1;
k < anc.size(); ++
k)
513 const size_t INF = std::numeric_limits<size_t>::max() / 4;
514 std::vector<size_t>
best(cd.
size(), INF);
515 std::vector<char> active(values.size(), 0);
522 [&](
const size_t c,
const size_t d,
const size_t)
529 auto query = [&](
const size_t u)
534 [&](
const size_t c,
const size_t d,
const size_t)
545 for (
size_t v = 0; v < active.size(); ++v)
551 std::mt19937
rng(0xC3E7D01Du);
552 std::uniform_int_distribution<size_t>
pick_id(0, values.size() - 1);
556 for (
size_t it = 0; it < 300; ++it)
559 if ((
rng() % 100) < 40)
Heavy-Light and Centroid decomposition on rooted trees represented as Aleph graphs.
TYPED_TEST_SUITE(AStarHeapTest, HeapTypes)
WeightedDigraph::Node Node
Simple dynamic array with automatic resizing and functional operations.
static Array create(size_t n)
Create an array with n logical elements.
Centroid decomposition over a rooted tree represented as an Aleph graph.
bool is_empty() const noexcept
size_t centroid_level_of_id(const size_t id) const
Level of centroid id in centroid tree (root level = 0).
Node * centroid_root() const noexcept
Root centroid node of the centroid tree (or nullptr if empty).
size_t centroid_root_id() const noexcept
Root centroid ID of the centroid tree (or NONE if empty).
const Array< size_t > & centroid_ancestors_of_id(const size_t id) const
Centroid ancestors of node ID from centroid root down to local centroid.
size_t centroid_parent_id(const size_t id) const
Parent centroid ID of id (or NONE if centroid root).
void for_each_centroid_ancestor_id(const size_t node, F &&f) const
Visit each centroid ancestor of node ID.
size_t id_of(const Node *node) const
const Array< size_t > & centroid_distances_of_id(const size_t id) const
Distances to centroid ancestors (aligned with centroid_ancestors_of_id).
size_t size() const noexcept
Segment-tree-powered path/subtree queries over an HLD layout.
T query_subtree(const Node *node) const
Subtree query for node in O(log n).
void set_node(const Node *node, const T &value)
Point assignment: a[node] = value.
T query_path(const Node *u, const Node *v) const
Path query between two nodes in O(log^2 n).
void update_node(const Node *node, const T &delta)
Point update: a[node] = Op(a[node], delta).
const Gen_Heavy_Light_Decomposition< GT, SA > & decomposition() const noexcept
T query_path_id(const size_t u, const size_t v) const
Path query between two node IDs in O(log^2 n).
bool is_empty() const noexcept
Heavy-Light Decomposition over a rooted tree represented as an Aleph graph.
Arc for graphs implemented with simple adjacency lists.
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Graph_Node< Node_Info > Node
The graph type.
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Graph class implemented with singly-linked adjacency lists.
__gmp_expr< T, __gmp_binary_expr< __gmp_expr< T, U >, unsigned long int, __gmp_root_function > > root(const __gmp_expr< T, U > &expr, unsigned long int l)
DynArray< Graph::Node * > nodes
Main namespace for Aleph-w library functions.
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
void next()
Advance all underlying iterators (bounds-checked).
Container< T > range(const T start, const T end, const T step=1)
Generate a range of values [start, end] with a given step.
T sum(const Container &container, const T &init=T{})
Compute sum of all elements.
Arc of graph implemented with double-linked adjacency lists.
Array-based graph implementation.
Generic graph and digraph implementations.
Simple graph implementation with adjacency lists.
TYPED_TEST(TreeDecompositionTypedTest, EmptyGraph)