69# ifndef TPL_LINK_CUT_TREE_H
70# define TPL_LINK_CUT_TREE_H
73# include <initializer_list>
76# include <type_traits>
97 template <
typename M,
typename T>
106 template <
typename L,
typename T>
108 std::equality_comparable<typename L::tag_type>
and
109 requires(
const typename L::tag_type &
t1,
110 const typename L::tag_type &
t2,
111 const T & val,
size_t cnt)
113 typename L::tag_type;
114 { L::tag_identity() } -> std::convertible_to<typename L::tag_type>;
115 { L::apply(val,
t1, cnt) } -> std::convertible_to<T>;
116 { L::compose(
t1,
t2) } -> std::convertible_to<typename L::tag_type>;
124 template <
typename T>
128 static constexpr T combine(
const T &,
const T & b)
noexcept {
return b; }
132 template <
typename T>
139 static constexpr T combine(
const T & a,
const T & b)
noexcept
146 template <
typename T>
151 return std::numeric_limits<T>::max();
154 static constexpr T combine(
const T & a,
const T & b)
noexcept
156 return a < b ? a : b;
161 template <
typename T>
166 return std::numeric_limits<T>::lowest();
169 static constexpr T combine(
const T & a,
const T & b)
noexcept
171 return a > b ? a : b;
176 template <
typename T>
181 static constexpr T combine(
const T & a,
const T & b)
noexcept
188 template <
typename T>
193 static constexpr T combine(
const T & a,
const T & b)
noexcept
195 T x = a <
T{0} ? -a : a;
196 T y = b <
T{0} ? -b : b;
208 template <
typename T>
213 static constexpr T combine(
const T & a,
const T & b)
noexcept
224 template <
typename T>
229 static constexpr T apply(
const T & v,
bool,
size_t)
noexcept {
return v; }
230 static constexpr bool compose(
bool,
bool)
noexcept {
return false; }
239 template <
typename T>
245 static constexpr T apply(
const T & v,
const T & tag,
size_t cnt)
noexcept
247 return v + tag *
static_cast<T>(cnt);
250 static constexpr T compose(
const T & a,
const T & b)
noexcept
265 template <
typename T>
285 return tag.active ? tag.val *
static_cast<T>(cnt) : v;
296 template <
class Mono
id,
class =
void>
300 template <
class Mono
id>
302 : std::bool_constant<Monoid::supports_counted_lazy::value> {};
305 template <
class LazyTag,
typename T>
309 template <
typename T>
313 template <
typename T>
354 template <
typename T =
int,
362 "AddLazyTag::apply and AssignLazyTag::apply require a monoid "
363 "with supports_counted_lazy=true");
402 return x->parent ==
nullptr or
403 (x->parent->left != x
and x->parent->right != x);
408 return x->parent
and x->parent->left == x;
420 std::swap(x->left, x->right);
421 if (x->left) x->left->rev ^=
true;
422 if (x->right) x->right->rev ^=
true;
426 if constexpr (
not std::is_same_v<LazyTag, NoLazyTag<T>>)
428 if (
not (x->lazy == LazyTag::tag_identity()))
434 c->val = LazyTag::apply(c->val, x->lazy, 1);
435 c->agg = LazyTag::apply(c->agg, x->lazy, c->sz);
436 c->lazy = LazyTag::compose(c->lazy, x->lazy);
440 x->lazy = LazyTag::tag_identity();
457 x->sz += x->left->sz;
458 x->agg = Monoid::combine(x->left->agg, x->agg);
462 x->sz += x->right->sz;
463 x->agg = Monoid::combine(x->agg, x->right->agg);
519 while (
not stk.is_empty())
544 Node *last =
nullptr;
545 for (
Node *u = x; u !=
nullptr; u = u->
parent)
558 template <
typename Op>
584 for (
size_t i = 0; i <
nodes.
size(); ++i)
624 auto *
nd =
new Node(std::move(val));
644 <<
"vertex does not belong to this link-cut tree";
648 <<
"vertex must be isolated";
697 if (x->
left ==
nullptr)
772 <<
"edge does not exist";
889 requires (
not std::is_same_v<LazyTag, NoLazyTag<T>>)
895 v->val = LazyTag::apply(v->val, tag, 1);
896 v->agg = LazyTag::apply(v->agg, tag, v->sz);
897 v->lazy = LazyTag::compose(v->lazy, tag);
918 for (
size_t i = 0; i <
nodes.
size(); ++i)
961 template <
typename Op>
964 for (
size_t i = 0; i <
nodes.
size(); ++i)
973 template <
typename Op>
984 for (
size_t i =
rev_path.size(); i > 0; --i)
1004 Node *prev =
nullptr;
1005 for (
const auto & v:
vals)
1023 for (
const auto & v:
vals)
1032 template <
typename Container>
1035 for (
const auto & [u, v]: edges)
1075 for (
size_t i = 0; i <
tree_nodes.size(); ++i)
1080 for (
size_t i = 0; i <
lct_nodes.size(); ++i)
1089 void operator()(
TN *
nd)
const noexcept
1098 for (
size_t i = 0; i <
lct_nodes.size(); ++i)
1106 std::unique_ptr<TN> child(
new TN(
lct_nodes(i)->val));
1107 tree_nodes(pi)->insert_rightmost_child(child.get());
C++20 concepts hub: comparison, BST policy, and Aleph container concepts.
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
void destroy_tree(Tree &tree)
WeightedDigraph::Node Node
Stack implemented with simple dynamic array and with bounds verification.
T & push(const T &data)
Push into stack a copy of data
Simple dynamic array with automatic resizing and functional operations.
constexpr size_t size() const noexcept
Return the number of elements stored in the stack.
T & append(const T &data)
Append a copy of data
Dynamic forest with path queries via Link-Cut Trees.
Gen_Link_Cut_Tree()=default
Default constructor for an empty Link-Cut Tree.
void set_val(Node *x, const T &val)
Update the payload value of vertex x and recompute aggregates.
size_t path_size(Node *u, Node *v)
Number of vertices on the path from u to v.
void destroy_vertex(Node *x)
Destroy an isolated vertex.
const T & get_val(Node *x)
Read the payload value of vertex x.
void make_root(Node *x)
Make x the root of its represented tree.
size_t tree_size(Node *x)
Number of vertices in the tree containing x.
void path_apply(Node *u, Node *v, const typename LazyTag::tag_type &tag)
Apply a lazy tag to every vertex on the path from u to v.
Tree_Node< T > * export_to_tree_node(Node *root)
Export the represented tree rooted at root as a Tree_Node<T>.
T path_query(Node *u, Node *v)
Aggregate (under Monoid) over all vertex values on the path from u to v.
size_t depth(Node *x)
Depth of x relative to the current root of its tree.
Node * find_root(Node *x)
Find the root of the represented tree containing x.
Gen_Link_Cut_Tree(Gen_Link_Cut_Tree &&)=delete
Deleted move constructor.
void for_each_node(Op &&op) const
Call op(Node *) for every vertex in the forest.
Gen_Link_Cut_Tree & operator=(const Gen_Link_Cut_Tree &)=delete
Deleted copy assignment.
size_t num_components() const noexcept
Number of connected components (trees) in the forest.
Node * parent(Node *x)
Parent of x in the represented tree under the current rooting.
Gen_Link_Cut_Tree(const Gen_Link_Cut_Tree &)=delete
Deleted copy constructor.
~Gen_Link_Cut_Tree()
Destructor.
Node * make_vertex(T &&val)
Create an isolated vertex (move semantics).
static void push(Node *x) noexcept
static Node * access(Node *x) noexcept
bool connected(Node *u, Node *v)
Test whether u and v are in the same represented tree.
void for_each_on_path(Node *u, Node *v, Op &&op)
Call op(Node *) for every vertex on the path from u to v, in order from u to v.
Node * make_vertex(const T &val=T{})
Create an isolated vertex with payload val.
static void rotate(Node *x) noexcept
Gen_Link_Cut_Tree & operator=(Gen_Link_Cut_Tree &&)=delete
Deleted move assignment.
void link_edges(const Container &edges)
Link every pair in an edge container.
Array< Node * > make_vertices(std::initializer_list< T > vals)
Create isolated vertices from an initializer list of values.
void link(Node *u, Node *v)
Add an edge between u and v, merging their trees.
static bool is_root(const Node *x) noexcept
static void inorder_traverse(Node *root, Op &&op)
static bool is_left(const Node *x) noexcept
static void pull(Node *x) noexcept
size_t size() const noexcept
Total number of vertices currently in the forest.
Node * lca(Node *u, Node *v)
Lowest common ancestor of u and v.
void cut(Node *u, Node *v)
Remove the represented edge between u and v.
Array< Node * > make_path(std::initializer_list< T > vals)
Create a path of vertices from an initializer list of values.
static void splay(Node *x) noexcept
Forward declaration used by CRTP helpers before the full node definition.
Concept for a lazy-tag policy used in deferred path updates.
Concept for a monoidal combiner over path values.
A static monoid: M::identity() and M::combine(a, b).
__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)
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
std::decay_t< typename HeadC::Item_Type > T
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Additive lazy tag: adds a delta to every node on a path.
static constexpr T apply(const T &v, const T &tag, size_t cnt) noexcept
static constexpr T compose(const T &a, const T &b) noexcept
static constexpr T tag_identity() noexcept
Payload for the assignment lazy tag.
constexpr bool operator==(const tag_type &o) const noexcept
Assignment lazy tag: sets every node on a path to a fixed value.
static constexpr T apply(const T &v, const tag_type &tag, size_t cnt) noexcept
static constexpr tag_type compose(const tag_type &existing, const tag_type &newer) noexcept
static constexpr tag_type tag_identity() noexcept
Default (no-op) monoid for connectivity-only usage.
static constexpr T identity() noexcept
static constexpr T combine(const T &, const T &b) noexcept
GCD monoid: identity = 0 (since gcd(0, x) = x), combine = gcd.
static constexpr T combine(const T &a, const T &b) noexcept
static constexpr T identity() noexcept
Internal node of the Link-Cut Tree (opaque handle).
typename LazyTag::tag_type tag_type
const T & get_val() const noexcept
Return the raw stored value without forcing synchronization.
Max monoid: identity = numeric lowest, combine = max(a, b).
static constexpr T identity() noexcept
static constexpr T combine(const T &a, const T &b) noexcept
Min monoid: identity = numeric max, combine = min(a, b).
static constexpr T combine(const T &a, const T &b) noexcept
static constexpr T identity() noexcept
No-op lazy tag (default — no deferred path updates).
static constexpr bool tag_identity() noexcept
static constexpr T apply(const T &v, bool, size_t) noexcept
static constexpr bool compose(bool, bool) noexcept
Product monoid: identity = 1, combine = a * b.
static constexpr T combine(const T &a, const T &b) noexcept
static constexpr T identity() noexcept
Sum monoid: identity = 0, combine = a + b.
static constexpr T combine(const T &a, const T &b) noexcept
std::true_type supports_counted_lazy
static constexpr T identity() noexcept
XOR monoid: identity = 0, combine = a ^ b.
static constexpr T identity() noexcept
static constexpr T combine(const T &a, const T &b) noexcept
Metafunction to check if a tag is a counted lazy tag.
Metafunction to check if a monoid supports counted lazy tags.
Stack implementations backed by dynamic or fixed arrays.
Dynamic array container with automatic resizing.
General tree (n-ary tree) node.