125 template <
class GT,
class SA>
132 static constexpr size_t NONE = std::numeric_limits<size_t>::max();
160 return std::make_pair(u, v);
170 <<
"Rooted_Tree_Data: root node provided but graph is empty";
183 Node * p = it.get_curr();
190 <<
"Rooted_Tree_Data: failed to index all graph nodes";
192 if (
root_ ==
nullptr)
196 <<
"Rooted_Tree_Data: root node does not belong to graph";
208 for (
size_t i = 0; i <
n_; ++i)
216 Arc * a = it.get_curr_ne();
224 <<
"Rooted_Tree_Data: arc endpoint is not indexed";
230 <<
"Rooted_Tree_Data: self-loop detected in filtered graph";
234 <<
"Rooted_Tree_Data: parallel/duplicate edge detected in filtered graph";
241 <<
"Rooted_Tree_Data: filtered graph is not a tree (expected "
245 it.has_curr(); it.next_ne())
247 const auto & [
fst,
snd] = it.get_curr();
248 const size_t u =
fst.first;
249 const size_t v =
fst.second;
267 for (
size_t i = 0; i <
n_; ++i)
271 for (
size_t i = 0; i <
n_; ++i)
299 auto &
fr = stack.
top();
311 if (
nxt ==
fr.parent)
315 <<
"Rooted_Tree_Data: filtered graph is not acyclic";
331 <<
"Rooted_Tree_Data: filtered graph is not connected";
334 <<
"Rooted_Tree_Data: unexpected Euler tour size";
340 <<
where <<
": id=" <<
id <<
" is out of range [0, " <<
n_ <<
")";
369 <<
"Rooted_Tree_Data::id_of: null node";
373 <<
"Rooted_Tree_Data::id_of: node does not belong to graph";
380 check_id(
id,
"Rooted_Tree_Data::node_of");
391 check_id(u,
"Rooted_Tree_Data::is_ancestor");
392 check_id(v,
"Rooted_Tree_Data::is_ancestor");
408 if (a.depth < b.depth)
410 if (b.depth < a.depth)
412 return (a.node <= b.node) ? a : b;
438 template <
class GT,
class SA = Dft_Show_Arc<GT>>
454 size_t &
up_at(
const size_t k,
const size_t v)
noexcept
456 return up_(
k *
n() + v);
461 return up_(
k *
n() + v);
475 levels_ =
static_cast<size_t>(std::bit_width(
n()));
478 for (
size_t i = 0; i <
levels_ *
n(); ++i)
481 for (
size_t v = 0; v <
n(); ++v)
485 for (
size_t v = 0; v <
n(); ++v)
496 if ((delta >>
k) & 1U)
645 <<
"Gen_Binary_Lifting_LCA::lca_id: internal invalid parent";
658 const size_t a =
lca_id(u, v);
690 template <
class GT,
class SA = Dft_Show_Arc<GT>>
825 return rmq_.query(
l,
r).node;
837 const size_t a =
lca_id(u, v);
862 template <
class GT,
class SA = Dft_Show_Arc<GT>>
866 template <
class GT,
class SA = Dft_Show_Arc<GT>>
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
#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.
Simple dynamic array with automatic resizing and functional operations.
static Array create(size_t n)
Create an array with n logical elements.
Dynamic stack of elements of generic type T based on a singly linked list.
T & top()
Return a modifiable reference to the top item of the stack.
bool is_empty() const noexcept
Check if the stack is empty.
T pop()
Remove and return the top item of the stack.
T & push(const T &data)
Push an item by copy onto the top of the stack.
Generic key-value map implemented on top of a binary search tree.
typename Base::Iterator Iterator
void next_ne() noexcept
Advances the iterator to the next filtered element (noexcept version).
LCA via binary lifting on a rooted tree.
size_t depth_of(const Node *node) const
Distance from root to node.
size_t depth_of_id(const size_t id) const
Distance from root to node by ID.
Gen_Binary_Lifting_LCA(const GT &g, Node *root, SA sa=SA())
Construct from graph + explicit root.
bool is_empty() const noexcept
Returns true if the tree has no nodes.
Node * node_of(const size_t id) const
Map an internal ID [0, n-1] back to a Node pointer.
size_t parent_id(const size_t id) const
Parent ID of node id, or NONE if root.
size_t n() const noexcept
size_t num_levels() const noexcept
Returns the number of levels in the jump table ( ).
size_t distance_id(const size_t u, const size_t v) const
Number of edges on the path between two ids in O(log n).
bool is_ancestor(const Node *u, const Node *v) const
Returns true if node u is an ancestor of v (or u == v).
Node * kth_ancestor(const Node *node, const size_t k) const
k-th ancestor by node pointer in O(log n).
Gen_Binary_Lifting_LCA(const GT &g, SA sa=SA())
Construct using the first graph node as root.
size_t kth_ancestor_id(const size_t id, const size_t k) const
k-th ancestor by id in O(log n).
size_t & up_at(const size_t k, const size_t v) noexcept
size_t up_at(const size_t k, const size_t v) const noexcept
size_t id_of(const Node *node) const
Map a Node pointer to its internal ID [0, n-1].
Node * root() const noexcept
Returns the root node of the tree.
size_t lift(size_t v, size_t delta) const
bool is_ancestor_id(const size_t u, const size_t v) const
Returns true if node u is an ancestor of v (or u == v).
size_t distance(const Node *u, const Node *v) const
Number of edges on the path between two nodes in O(log n).
size_t size() const noexcept
Total number of nodes in the tree.
static constexpr size_t NONE
size_t root_id() const noexcept
Returns the internal ID of the root node.
size_t lca_id(size_t u, size_t v) const
LCA query by node ids in O(log n).
Node * parent_of(const Node *node) const
Parent of node, or nullptr if root.
Node * lca(const Node *u, const Node *v) const
LCA query by node pointers in O(log n).
void ensure_not_empty(const char *where) const
LCA via Euler tour + RMQ on depth in a rooted tree.
Node * parent_of(const Node *node) const
Parent of node, or nullptr if root.
static constexpr size_t NONE
Node * node_of(const size_t id) const
Map an internal ID [0, n-1] back to a Node pointer.
bool is_empty() const noexcept
Returns true if the tree has no nodes.
lca_detail::Depth_Node_Min_Op Depth_Node_Min_Op
Gen_Euler_RMQ_LCA(const GT &g, SA sa=SA())
Construct using the first graph node as root.
bool is_ancestor(const Node *u, const Node *v) const
Returns true if node u is an ancestor of v (or u == v).
size_t id_of(const Node *node) const
Map a Node pointer to its internal ID [0, n-1].
size_t depth_of_id(const size_t id) const
Distance from root to node by ID.
size_t lca_id(const size_t u, const size_t v) const
LCA query by node ids in O(1).
void ensure_not_empty(const char *where) const
size_t size() const noexcept
Total number of nodes in the tree.
Node * root() const noexcept
Returns the root node of the tree.
size_t distance_id(const size_t u, const size_t v) const
Number of edges on the path between two ids in O(1).
Gen_Euler_RMQ_LCA(const GT &g, Node *root, SA sa=SA())
Construct from graph + explicit root.
size_t root_id() const noexcept
Returns the internal ID of the root node.
size_t depth_of(const Node *node) const
Distance from root to node.
size_t parent_id(const size_t id) const
Parent ID of node id, or NONE if root.
Node * lca(const Node *u, const Node *v) const
LCA query by node pointers in O(1).
bool is_ancestor_id(const size_t u, const size_t v) const
Returns true if node u is an ancestor of v (or u == v).
size_t euler_tour_size() const noexcept
Euler tour size ( for empty tree, else ).
const Array< size_t > & euler_tour() const noexcept
Euler tour sequence of node ids ( entries).
size_t distance(const Node *u, const Node *v) const
Number of edges on the path between two nodes in O(1).
Gen_Sparse_Table< Depth_Node, Depth_Node_Min_Op > rmq_
Array< Depth_Node > euler_depth_
Sparse Table over an arbitrary associative and idempotent binary operation.
Graph_Node< Node_Info > Node
The graph type.
Graph_Arc< Arc_Info > Arc
The node class type.
Filtered iterator on the nodes of a graph.
void build_simple_adjacency()
Rooted_Tree_Data(const GT &g, Node *root, SA sa=SA())
size_t root_id() const noexcept
const Array< size_t > & depth() const noexcept
Array< Array< size_t > > adjacency_
MapOLhash< Node *, size_t > node_to_id_
size_t size() const noexcept
const Array< Node * > & id_to_node() const noexcept
size_t euler_size() const noexcept
Array< Node * > id_to_node_
const Array< size_t > & euler() const noexcept
static constexpr size_t NONE
static Pair_Key normalize_pair(size_t u, size_t v) noexcept
void check_id(const size_t id, const char *where) const
Node * root() const noexcept
bool is_ancestor(const size_t u, const size_t v) const
const Array< size_t > & first() const noexcept
const Array< size_t > & tout() const noexcept
const Array< size_t > & tin() const noexcept
Node * node_of(const size_t id) const
const Array< size_t > & parent() const noexcept
void validate_id(const size_t id, const char *where) const
size_t id_of(const Node *node) const
std::pair< size_t, size_t > Pair_Key
bool is_empty() const noexcept
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Main namespace for Aleph-w library functions.
and
Check uniqueness with explicit hash + equality functors.
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.
Filtered iterator on all the arcs of a graph.
Open addressing hash map using linear probing.
Data & find(const Key &key)
Find and return the value for a key.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair (copy semantics).
Pair * search(const Key &key) const noexcept
Search for a key in the map.
Depth_Node operator()(const Depth_Node &a, const Depth_Node &b) const noexcept
Dynamic array container with automatic resizing.
Dynamic stack implementation based on linked lists.
Dynamic map with open hashing.
Dynamic key-value map based on balanced binary search trees.
Generic graph and digraph implementations.
Sparse Table for static range queries in O(1).