89# ifndef TPL_MO_ON_TREES_H
90# define TPL_MO_ON_TREES_H
125 typename GT::Node_Arc_Iterator;
126 { g.
vsize() } -> std::convertible_to<size_t>;
128 {
typename GT::Node_Arc_Iterator(p) };
167 template <AlephGraph GT,
class Policy>
174 using T =
typename Node::Node_Type;
234 <<
"Gen_Mo_On_Trees: root node not found in graph";
242 for (
auto it =
typename GT::Node_Arc_Iterator(p);
243 it.has_curr(); it.next_ne())
245 auto * a = it.get_curr();
261 for (
size_t i = 0; i <
n_; ++i)
265 for (
size_t i = 0; i <
n_; ++i)
271 struct Frame {
size_t id;
size_t child_idx; };
275 visited(root_id) =
true;
287 stk.push({root_id, 0});
289 while (
not stk.is_empty())
291 auto &
fr =
stk.top();
294 while (
fr.child_idx < adj(
fr.id).size())
296 const size_t nid = adj(
fr.id)(
fr.child_idx++);
330 <<
"Gen_Mo_On_Trees: graph is not connected (not a tree)";
334 while ((
static_cast<size_t>(1) <<
log_n_) <
n_)
339 for (
size_t i = 0; i <
log_n_ *
n_; ++i)
342 for (
size_t v = 0; v <
n_; ++v)
346 for (
size_t v = 0; v <
n_; ++v)
353 size_t lca(
size_t u,
size_t v)
const
366 for (
int k =
static_cast<int>(
log_n_) - 1;
k >= 0; --
k)
373 return up_(0 *
n_ + u);
381 const size_t q =
queries.size();
382 const size_t block = std::max<size_t>(
383 1,
static_cast<size_t>(std::sqrt(
static_cast<double>(n))));
388 const size_t ba = a.
l / block;
389 const size_t bb = b.
l / block;
392 return (
ba & 1) ? (a.
r > b.
r) : (a.
r < b.
r);
408 for (
size_t i = 1; i < q; ++i)
489 for (
size_t i = 0; i < q; ++i)
493 <<
"subtree_solve: query " << i <<
" node not in tree";
494 const size_t id = p->second;
513 std::initializer_list<Node*>
il)
const
550 size_t l,
r, id, lca_id;
554 for (
size_t i = 0; i < q; ++i)
559 <<
"path_solve: query " << i <<
" node not in tree";
561 size_t u =
pu->second;
562 size_t v =
pv->second;
575 const size_t block = std::max<size_t>(
576 1,
static_cast<size_t>(
577 std::sqrt(
static_cast<double>(
tour_sz))));
582 const size_t ba = a.l / block;
583 const size_t bb = b.l / block;
586 return (
ba & 1) ? (a.r > b.r) : (a.r < b.r);
593 for (
size_t i = 0; i <
n_; ++i)
597 auto toggle = [&](
const size_t pos)
629 for (
size_t i = 1; i < q; ++i)
665 std::initializer_list<std::pair<Node*, Node*>>
il)
const
700 template <
typename T,
class Policy>
742 if (
root_ ==
nullptr)
750 while (
not stk.is_empty())
759 c = c->get_right_sibling())
784 Node * mp = it.get_curr();
792 for (
size_t pid = 0; pid <
n_; ++pid)
798 c = c->get_right_sibling())
819 for (
size_t i = 0; i <
n_; ++i)
823 for (
size_t i = 0; i <
n_; ++i)
829 struct Frame {
size_t id;
size_t child_idx; };
833 visited(root_id) =
true;
845 stk.push({root_id, 0});
847 while (
not stk.is_empty())
849 auto &
fr =
stk.top();
852 while (
fr.child_idx < adj(
fr.id).size())
854 const size_t nid = adj(
fr.id)(
fr.child_idx++);
888 <<
"Gen_Mo_On_Tree_Node: tree traversal inconsistency";
892 while ((
static_cast<size_t>(1) <<
log_n_) <
n_)
897 for (
size_t i = 0; i <
log_n_ *
n_; ++i)
900 for (
size_t v = 0; v <
n_; ++v)
904 for (
size_t v = 0; v <
n_; ++v)
911 size_t lca(
size_t u,
size_t v)
const
924 for (
int k =
static_cast<int>(
log_n_) - 1;
k >= 0; --
k)
931 return up_(0 *
n_ + u);
939 const size_t q =
queries.size();
940 const size_t block = std::max<size_t>(
941 1,
static_cast<size_t>(std::sqrt(
static_cast<double>(
nn))));
946 const size_t ba = a.
l / block;
947 const size_t bb = b.
l / block;
950 return (
ba & 1) ? (a.
r > b.
r) : (a.
r < b.
r);
966 for (
size_t i = 1; i < q; ++i)
1001 <<
"Gen_Mo_On_Tree_Node: root is null";
1033 for (
size_t i = 0; i < q; ++i)
1037 <<
"subtree_solve: query " << i <<
" node not in tree";
1038 const size_t id = p->second;
1057 std::initializer_list<Node*>
il)
const
1086 size_t l,
r, id, lca_id;
1090 for (
size_t i = 0; i < q; ++i)
1095 <<
"path_solve: query " << i <<
" node not in tree";
1097 size_t u =
pu->second;
1098 size_t v =
pv->second;
1113 const size_t block = std::max<size_t>(
1114 1,
static_cast<size_t>(
1115 std::sqrt(
static_cast<double>(
tour_sz))));
1120 const size_t ba = a.l / block;
1121 const size_t bb = b.l / block;
1124 return (
ba & 1) ? (a.r > b.r) : (a.r < b.r);
1131 for (
size_t i = 0; i <
n_; ++i)
1134 auto toggle = [&](
const size_t pos)
1139 active(
nid) =
false;
1164 for (
size_t i = 1; i < q; ++i)
1200 std::initializer_list<std::pair<Node*, Node*>>
il)
const
1242 template <
typename T>
1250 template <
typename T>
1258 template <
typename T>
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
C++20 concepts for the protocol shared by graph algorithms.
List_Graph< Graph_Node< Node_Info >, Graph_Arc< Arc_Info > > GT
Simple dynamic array with automatic resizing and functional operations.
static Array create(size_t n)
Create an array with n logical elements.
T & append()
Allocate a new entry to the end of array.
Dynamic stack of elements of generic type T based on a singly linked list.
T & push(const T &data)
Push an item by copy onto the top of the stack.
Doubly-linked list (defined in tpl_dynList.H).
T & append(const T &item)
Offline subtree and path queries on N-ary trees (Tree_Node).
static constexpr size_t NONE
Array< answer_type > path_solve(std::initializer_list< std::pair< Node *, Node * > > il) const
Solve path queries (initializer-list overload).
size_t size() const noexcept
Number of nodes in the tree.
size_t lca(size_t u, size_t v) const
MapOLhash< Node *, size_t > node_to_id_
typename Policy::answer_type answer_type
Array< size_t > flat_node_
Array< answer_type > mo_sweep(const Array< T > &data, Array< Mo_Query > queries, size_t nn) const
Array< answer_type > path_solve(const Array< std::pair< Node *, Node * > > &query_pairs) const
Answer path queries on the N-ary tree.
Array< Node * > id_to_node_
Array< answer_type > subtree_solve(std::initializer_list< Node * > il) const
Solve subtree queries (initializer-list overload).
Array< answer_type > subtree_solve(const Array< Node * > &query_roots) const
Answer subtree queries on the N-ary tree.
Gen_Mo_On_Tree_Node(Node *root, Policy p=Policy())
Construct a Mo's algorithm query engine for N-ary trees.
bool is_empty() const noexcept
True if the tree is empty.
Offline subtree and path queries on trees via Mo's algorithm.
typename Policy::answer_type answer_type
typename Node::Node_Type T
Array< answer_type > path_solve(std::initializer_list< std::pair< Node *, Node * > > il) const
Solve path queries (initializer-list overload).
static constexpr size_t NONE
Array< answer_type > subtree_solve(const Array< Node * > &query_roots) const
Answer subtree queries using Mo's algorithm.
Array< Node * > id_to_node_
bool is_empty() const noexcept
True if the tree is empty.
Array< size_t > flat_node_
Array< answer_type > subtree_solve(std::initializer_list< Node * > il) const
Answer subtree queries from an initializer list.
Gen_Mo_On_Trees(const GT &g, Node *root, Policy p=Policy())
Construct a Mo's algorithm query engine for tree queries.
size_t lca(size_t u, size_t v) const
MapOLhash< Node *, size_t > node_to_id_
size_t size() const noexcept
Number of nodes in the tree.
Array< answer_type > mo_sweep(const Array< T > &data, Array< Mo_Query > queries, size_t n) const
Array< answer_type > path_solve(const Array< std::pair< Node *, Node * > > &query_pairs) const
Answer path queries between node pairs.
typename Node::Node_Type Node_Type
The arc class type.
Graph_Node< Node_Info > Node
The graph type.
Graph_Arc< Arc_Info > Arc
The node class type.
Forward declaration used by CRTP helpers before the full node definition.
Tree_Node * get_left_child() const noexcept
Returns the leftmost child of this.
Tree_Node * get_parent() const noexcept
Returns the parent of this.
T & get_key() noexcept
Returns a modifiable reference to the node contents.
Node * get_connected_node(Arc *arc, Node *node) const noexcept
Return the adjacent node to node through arc.
void for_each_node(Operation &operation) const
Unconditionally traverse all the nodes of graph and on each one perform an operation.
constexpr size_t vsize() const noexcept
Concept constraining a policy for Mo's algorithm.
Concept constraining a graph type usable for Mo on Trees.
__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.
bool diff(const C1 &c1, const C2 &c2, Eq e=Eq())
Check if two containers differ.
Policy: count distinct elements in a range.
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.
A query for Mo's algorithm: inclusive range [l, r] with id.
size_t l
Left endpoint (inclusive, 0-based).
size_t r
Right endpoint (inclusive, 0-based).
Policy: "powerful array" sum = sum(cnt[x]^2 * x).
Policy: range mode (most frequent element).
Dynamic array container with automatic resizing.
Dynamic stack implementation based on linked lists.
Alias for htlist.H (DynList implementation).
Dynamic map with open hashing.
Mo's algorithm for offline range queries.
General tree (n-ary tree) node.