Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
HLD.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
31
90#ifndef HLD_H
91#define HLD_H
92
93# include <algorithm>
94# include <cstddef>
95# include <limits>
96# include <utility>
97
98# include <ah-errors.H>
99# include <tpl_array.H>
100# include <tpl_dynListStack.H>
101# include <tpl_dynMapOhash.H>
102# include <tpl_dynMapTree.H>
103# include <tpl_graph.H>
104# include <tpl_segment_tree.H>
105
106namespace Aleph
107{
108 namespace hld_detail
109 {
118 template <class GT, class SA>
120 {
121 public:
122 using Node = typename GT::Node;
123 using Arc = typename GT::Arc;
124
125 static constexpr size_t NONE = std::numeric_limits<size_t>::max();
126
127 private:
128 using Pair_Key = std::pair<size_t, size_t>;
129
130 const GT * graph_ = nullptr;
132 Node * root_ = nullptr;
133 size_t root_id_ = NONE;
134
135 size_t n_ = 0;
136
139
144
145 // HLD-specific arrays
146 Array<size_t> pos_; // flat position in segment tree
147 Array<size_t> chain_head_; // head of the chain containing this node
148 Array<size_t> tin_; // entry time (same as pos_ for HLD)
149 Array<size_t> tout_; // exit time
150
151 size_t num_chains_ = 0;
152
153 static Pair_Key normalize_pair(size_t u, size_t v) noexcept
154 {
155 if (u > v)
156 std::swap(u, v);
157 return std::make_pair(u, v);
158 }
159
161 {
163
164 if (n_ == 0)
165 {
166 ah_domain_error_if(root_ != nullptr)
167 << "HLD_Tree_Data: root node provided but graph is empty";
168 return;
169 }
170
172 {
174 node_to_id_.swap(tmp);
175 }
176
177 size_t next_id = 0;
178 for (Node_Iterator<GT> it(*graph_); it.has_curr(); it.next_ne())
179 {
180 Node * p = it.get_curr();
181 id_to_node_(next_id) = p;
183 ++next_id;
184 }
185
187 << "HLD_Tree_Data: failed to index all graph nodes";
188
189 if (root_ == nullptr)
190 root_ = id_to_node_(0);
191
193 << "HLD_Tree_Data: root node does not belong to graph";
194
196 }
197
199 {
200 if (n_ == 0)
201 return;
202
203 adjacency_.empty();
204 adjacency_.reserve(n_);
205 for (size_t i = 0; i < n_; ++i)
206 adjacency_.append(Array<size_t>());
207
209 size_t edge_count = 0;
210
211 for (Arc_Iterator<GT, SA> it(*graph_, sa_); it.has_curr(); it.next_ne())
212 {
213 Arc * a = it.get_curr_ne();
214 Node * src = graph_->get_src_node(a);
215 Node * tgt = graph_->get_tgt_node(a);
216
217 const auto * src_item = node_to_id_.search(src);
218 const auto * tgt_item = node_to_id_.search(tgt);
219
220 ah_runtime_error_unless(src_item != nullptr and tgt_item != nullptr)
221 << "HLD_Tree_Data: arc endpoint is not indexed";
222
223 const size_t u = src_item->second;
224 const size_t v = tgt_item->second;
225
226 ah_domain_error_if(u == v)
227 << "HLD_Tree_Data: self-loop detected in filtered graph";
228
229 const Pair_Key key = normalize_pair(u, v);
230 ah_domain_error_if(unique_edges.search(key) != nullptr)
231 << "HLD_Tree_Data: parallel/duplicate edge detected in filtered graph";
232
233 unique_edges.insert(key, 1);
234 ++edge_count;
235 }
236
238 << "HLD_Tree_Data: filtered graph is not a tree (expected "
239 << (n_ - 1) << " edges, got " << edge_count << ")";
240
242 it.has_curr(); it.next_ne())
243 {
244 const auto & [fst, snd] = it.get_curr();
245 const size_t u = fst.first;
246 const size_t v = fst.second;
247 adjacency_(u).append(v);
248 adjacency_(v).append(u);
249 }
250 }
251
253 {
254 if (n_ == 0)
255 return;
256
260
261 for (size_t i = 0; i < n_; ++i)
262 {
263 parent_(i) = NONE;
264 subtree_size_(i) = 1;
265 }
266
268 for (size_t i = 0; i < n_; ++i)
269 visited(i) = 0;
270
271 struct Frame
272 {
273 size_t node;
274 size_t parent;
275 size_t next_child;
276 };
277
279
280 size_t visited_count = 1;
281 visited(root_id_) = 1;
282 depth_(root_id_) = 0;
284
285 stack.push({root_id_, NONE, 0});
286
287 while (not stack.is_empty())
288 {
289 auto & fr = stack.top();
290
291 if (fr.next_child == adjacency_(fr.node).size())
292 {
293 // All children processed; accumulate size into parent.
294 // Save fr.node before pop() invalidates the reference.
295 const size_t done = fr.node;
296 (void) stack.pop();
297 if (not stack.is_empty())
298 subtree_size_(stack.top().node) += subtree_size_(done);
299 continue;
300 }
301
302 const size_t nxt = adjacency_(fr.node)(fr.next_child++);
303 if (nxt == fr.parent)
304 continue;
305
306 ah_domain_error_if(visited(nxt))
307 << "HLD_Tree_Data: filtered graph is not acyclic";
308
309 visited(nxt) = 1;
311
312 parent_(nxt) = fr.node;
313 depth_(nxt) = depth_(fr.node) + 1;
314
315 stack.push({nxt, fr.node, 0});
316 }
317
319 << "HLD_Tree_Data: filtered graph is not connected";
320 }
321
323 {
324 if (n_ == 0)
325 return;
326
327 for (size_t u = 0; u < n_; ++u)
328 {
329 auto & adj = adjacency_(u);
330 if (adj.size() <= 1)
331 continue;
332
333 // Find the child with the largest subtree_size
334 size_t best_idx = NONE;
335 size_t best_size = 0;
336
337 for (size_t i = 0; i < adj.size(); ++i)
338 {
339 const size_t v = adj(i);
340 if (v == parent_(u))
341 continue;
342 if (subtree_size_(v) > best_size)
343 {
345 best_idx = i;
346 }
347 }
348
349 if (best_idx == NONE)
350 continue;
351
352 // Swap the heavy child to position 0 (or the first non-parent)
353 // Find the first non-parent position
354 size_t first_child_pos = 0;
355 if (adj(0) == parent_(u))
356 first_child_pos = 1;
357
359 std::swap(adj(best_idx), adj(first_child_pos));
360 }
361 }
362
364 {
365 if (n_ == 0)
366 return;
367
372
373 struct Frame
374 {
375 size_t node;
376 size_t parent;
377 size_t next_child;
378 size_t head;
379 };
380
382
383 size_t timer = 0;
384 num_chains_ = 0;
385
386 // Root starts a new chain
390 ++timer;
391 ++num_chains_;
392
393 stack.push({root_id_, NONE, 0, root_id_});
394
395 while (not stack.is_empty())
396 {
397 auto & fr = stack.top();
398
399 if (fr.next_child == adjacency_(fr.node).size())
400 {
401 tout_(fr.node) = timer - 1;
402 (void) stack.pop();
403 continue;
404 }
405
406 const size_t nxt = adjacency_(fr.node)(fr.next_child);
407 ++fr.next_child;
408
409 if (nxt == fr.parent)
410 continue;
411
412 // Determine if this is a heavy or light child
413 // The heavy child is the first non-parent child in adjacency
414 // (after reordering)
415 bool is_heavy = false;
416 {
417 const auto & adj = adjacency_(fr.node);
418 size_t first_child_pos = 0;
419 if (adj.size() > 0 and adj(0) == fr.parent)
420 first_child_pos = 1;
421 if (first_child_pos < adj.size() and adj(first_child_pos) == nxt)
422 is_heavy = true;
423 }
424
425 if (is_heavy)
426 {
427 chain_head_(nxt) = fr.head;
428 }
429 else
430 {
432 ++num_chains_;
433 }
434
435 pos_(nxt) = timer;
436 tin_(nxt) = timer;
437 ++timer;
438
439 stack.push({nxt, fr.node, 0, chain_head_(nxt)});
440 }
441 }
442
443 void check_id(const size_t id, const char * where) const
444 {
446 << where << ": id=" << id << " is out of range [0, " << n_ << ")";
447 }
448
449 public:
450 HLD_Tree_Data(const GT & g, Node * root, SA sa = SA())
451 : graph_(&g), sa_(std::move(sa)), root_(root)
452 {
453 index_nodes();
458 }
459
460 [[nodiscard]] size_t size() const noexcept { return n_; }
461 [[nodiscard]] bool is_empty() const noexcept { return n_ == 0; }
462 [[nodiscard]] Node * root() const noexcept { return root_; }
463 [[nodiscard]] size_t root_id() const noexcept { return root_id_; }
464
469 [[nodiscard]] const Array<size_t> & pos() const noexcept { return pos_; }
471 [[nodiscard]] const Array<size_t> & tin() const noexcept { return tin_; }
472 [[nodiscard]] const Array<size_t> & tout() const noexcept { return tout_; }
474
475 [[nodiscard]] size_t id_of(const Node * node) const
476 {
477 ah_invalid_argument_if(node == nullptr)
478 << "HLD_Tree_Data::id_of: null node";
479
480 const auto * item = node_to_id_.search(const_cast<Node *>(node));
481 ah_domain_error_if(item == nullptr)
482 << "HLD_Tree_Data::id_of: node does not belong to graph";
483
484 return item->second;
485 }
486
487 [[nodiscard]] Node * node_of(const size_t id) const
488 {
489 check_id(id, "HLD_Tree_Data::node_of");
490 return id_to_node_(id);
491 }
492
493 void validate_id(const size_t id, const char * where) const
494 {
495 check_id(id, where);
496 }
497 };
498 } // namespace hld_detail
499
500
524 template <class GT, typename T, class Op, class SA = Dft_Show_Arc<GT>>
525 requires SegmentTreeOp<Op, T>
527 {
528 public:
529 using Node = typename GT::Node;
530
531 private:
533 static constexpr size_t NONE = Topology::NONE;
534
537 Op op_;
539
540 [[nodiscard]] size_t n() const noexcept { return topology_.size(); }
541
542 void ensure_not_empty(const char * where) const
543 {
544 ah_domain_error_if(is_empty()) << where << ": tree is empty";
545 }
546
548 template <class NodeValueFn>
550 {
551 if (is_empty())
552 return;
553
554 auto flat = Array<T>::create(n());
555 for (size_t i = 0; i < n(); ++i)
556 flat(i) = identity_;
557
558 for (size_t id = 0; id < n(); ++id)
559 {
560 const size_t p = topology_.pos()(id);
562 }
563
565 seg_.swap(real_seg);
566 }
567
568 public:
579 template <class NodeValueFn>
581 const T & identity, Op oper = Op(), SA sa = SA())
582 : topology_(g, root, std::move(sa)),
583 identity_(identity),
584 op_(oper),
585 seg_(1, identity, identity, oper)
586 {
587 build_segment_tree(std::forward<NodeValueFn>(node_value));
588 }
589
591 template <class NodeValueFn>
593 const T & identity, Op oper = Op(), SA sa = SA())
594 : topology_(g, nullptr, std::move(sa)),
595 identity_(identity),
596 op_(oper),
597 seg_(1, identity, identity, oper)
598 {
599 build_segment_tree(std::forward<NodeValueFn>(node_value));
600 }
601
603 [[nodiscard]] size_t size() const noexcept { return topology_.size(); }
604
607
610
612 [[nodiscard]] size_t root_id() const noexcept { return topology_.root_id(); }
613
615 [[nodiscard]] Node * node_of(const size_t id) const
616 {
617 return topology_.node_of(id);
618 }
619
621 [[nodiscard]] size_t id_of(const Node * node) const
622 {
623 return topology_.id_of(node);
624 }
625
627 [[nodiscard]] size_t position(const size_t id) const
628 {
629 topology_.validate_id(id, "Gen_HLD::position");
630 return topology_.pos()(id);
631 }
632
634 [[nodiscard]] size_t chain_head_id(const size_t id) const
635 {
636 topology_.validate_id(id, "Gen_HLD::chain_head_id");
637 return topology_.chain_head()(id);
638 }
639
641 [[nodiscard]] size_t depth_of_id(const size_t id) const
642 {
643 topology_.validate_id(id, "Gen_HLD::depth_of_id");
644 return topology_.depth()(id);
645 }
646
648 [[nodiscard]] size_t depth_of(const Node * node) const
649 {
650 return depth_of_id(id_of(node));
651 }
652
654 [[nodiscard]] size_t subtree_size_of_id(const size_t id) const
655 {
656 topology_.validate_id(id, "Gen_HLD::subtree_size_of_id");
657 return topology_.subtree_size()(id);
658 }
659
661 [[nodiscard]] size_t subtree_size_of(const Node * node) const
662 {
663 return subtree_size_of_id(id_of(node));
664 }
665
667 [[nodiscard]] size_t parent_id(const size_t id) const
668 {
669 topology_.validate_id(id, "Gen_HLD::parent_id");
670 return topology_.parent()(id);
671 }
672
674 [[nodiscard]] Node * parent_of(const Node * node) const
675 {
676 const size_t pid = parent_id(id_of(node));
677 return pid == NONE ? nullptr : node_of(pid);
678 }
679
682 {
683 return topology_.num_chains();
684 }
685
686 // ------------------------------------------------------------------
687 // Path queries
688 // ------------------------------------------------------------------
689
699 [[nodiscard]] T path_query_id(size_t u, size_t v) const
700 {
701 ensure_not_empty("Gen_HLD::path_query_id");
702 topology_.validate_id(u, "Gen_HLD::path_query_id");
703 topology_.validate_id(v, "Gen_HLD::path_query_id");
704
705 T result = identity_;
706
707 while (topology_.chain_head()(u) != topology_.chain_head()(v))
708 {
709 // Move the deeper chain head up
710 if (topology_.depth()(topology_.chain_head()(u)) <
712 std::swap(u, v);
713
714 // Query the segment from chain_head(u) to u
715 const size_t head = topology_.chain_head()(u);
716 result = op_(result, seg_.query(topology_.pos()(head),
717 topology_.pos()(u)));
718 u = topology_.parent()(head);
719 }
720
721 // u and v are now on the same chain
722 if (topology_.depth()(u) > topology_.depth()(v))
723 std::swap(u, v);
724
725 result = op_(result, seg_.query(topology_.pos()(u),
726 topology_.pos()(v)));
727 return result;
728 }
729
731 [[nodiscard]] T path_query(const Node * u, const Node * v) const
732 {
733 return path_query_id(id_of(u), id_of(v));
734 }
735
741 [[nodiscard]] T path_query_edges_id(size_t u, size_t v) const
742 {
743 ensure_not_empty("Gen_HLD::path_query_edges_id");
744 topology_.validate_id(u, "Gen_HLD::path_query_edges_id");
745 topology_.validate_id(v, "Gen_HLD::path_query_edges_id");
746
747 T result = identity_;
748
749 while (topology_.chain_head()(u) != topology_.chain_head()(v))
750 {
751 if (topology_.depth()(topology_.chain_head()(u)) <
753 std::swap(u, v);
754
755 const size_t head = topology_.chain_head()(u);
756 result = op_(result, seg_.query(topology_.pos()(head),
757 topology_.pos()(u)));
758 u = topology_.parent()(head);
759 }
760
761 if (topology_.depth()(u) > topology_.depth()(v))
762 std::swap(u, v);
763
764 // Skip the LCA node (u) for edge-weighted queries
765 if (u != v)
766 result = op_(result, seg_.query(topology_.pos()(u) + 1,
767 topology_.pos()(v)));
768
769 return result;
770 }
771
773 [[nodiscard]] T path_query_edges(const Node * u, const Node * v) const
774 {
775 return path_query_edges_id(id_of(u), id_of(v));
776 }
777
778 // ------------------------------------------------------------------
779 // Subtree queries
780 // ------------------------------------------------------------------
781
786 [[nodiscard]] T subtree_query_id(const size_t v) const
787 {
788 ensure_not_empty("Gen_HLD::subtree_query_id");
789 topology_.validate_id(v, "Gen_HLD::subtree_query_id");
790
791 const size_t l = topology_.pos()(v);
792 const size_t r = l + topology_.subtree_size()(v) - 1;
793 return seg_.query(l, r);
794 }
795
797 [[nodiscard]] T subtree_query(const Node * v) const
798 {
799 return subtree_query_id(id_of(v));
800 }
801
802 // ------------------------------------------------------------------
803 // Point update
804 // ------------------------------------------------------------------
805
811 void point_update_id(const size_t v, const T & new_value)
812 {
813 ensure_not_empty("Gen_HLD::point_update_id");
814 topology_.validate_id(v, "Gen_HLD::point_update_id");
815
816 seg_.set(topology_.pos()(v), new_value);
817 }
818
820 void point_update(const Node * v, const T & new_value)
821 {
823 }
824
825 // ------------------------------------------------------------------
826 // LCA queries (free from chain walk)
827 // ------------------------------------------------------------------
828
830 [[nodiscard]] size_t lca_id(size_t u, size_t v) const
831 {
832 ensure_not_empty("Gen_HLD::lca_id");
833 topology_.validate_id(u, "Gen_HLD::lca_id");
834 topology_.validate_id(v, "Gen_HLD::lca_id");
835
836 while (topology_.chain_head()(u) != topology_.chain_head()(v))
837 {
838 if (topology_.depth()(topology_.chain_head()(u)) <
840 std::swap(u, v);
841
843 }
844
845 return topology_.depth()(u) <= topology_.depth()(v) ? u : v;
846 }
847
849 [[nodiscard]] Node * lca(const Node * u, const Node * v) const
850 {
851 return node_of(lca_id(id_of(u), id_of(v)));
852 }
853
854 // ------------------------------------------------------------------
855 // Distance queries
856 // ------------------------------------------------------------------
857
859 [[nodiscard]] size_t distance_id(const size_t u, const size_t v) const
860 {
861 const size_t a = lca_id(u, v);
862 return topology_.depth()(u) + topology_.depth()(v)
863 - 2 * topology_.depth()(a);
864 }
865
867 [[nodiscard]] size_t distance(const Node * u, const Node * v) const
868 {
869 return distance_id(id_of(u), id_of(v));
870 }
871
872 // ------------------------------------------------------------------
873 // Decomposition accessors (for power users)
874 // ------------------------------------------------------------------
875
881 {
882 return topology_.pos();
883 }
884
894
897 {
898 return topology_.depth();
899 }
900
906
909 {
910 return topology_.parent();
911 }
912
914 [[nodiscard]] T get_value_at_id(const size_t id) const
915 {
916 topology_.validate_id(id, "Gen_HLD::get_value_at_id");
917 return seg_.get(topology_.pos()(id));
918 }
919
921 [[nodiscard]] T get_value(const Node * v) const
922 {
923 return get_value_at_id(id_of(v));
924 }
925 };
926
927
928 // ====================================================================
929 // Convenience aliases
930 // ====================================================================
931
940 template <class GT, typename T, class SA = Dft_Show_Arc<GT>>
941 struct HLD_Sum : public Gen_HLD<GT, T, Aleph::plus<T>, SA>
942 {
944 using Node = typename GT::Node;
945
946 template <class NodeValueFn>
947 HLD_Sum(const GT & g, Node * root, NodeValueFn && nv, SA sa = SA())
948 : Base(g, root, std::forward<NodeValueFn>(nv),
949 T(), Aleph::plus<T>(), std::move(sa))
950 {}
951
952 template <class NodeValueFn>
953 HLD_Sum(const GT & g, NodeValueFn && nv, SA sa = SA())
954 : Base(g, std::forward<NodeValueFn>(nv),
955 T(), Aleph::plus<T>(), std::move(sa))
956 {}
957 };
958
967 template <class GT, typename T, class SA = Dft_Show_Arc<GT>>
968 struct HLD_Max : public Gen_HLD<GT, T, Max_Op<T>, SA>
969 {
971 using Node = typename GT::Node;
972
973 template <class NodeValueFn>
974 HLD_Max(const GT & g, Node * root, NodeValueFn && nv, SA sa = SA())
975 : Base(g, root, std::forward<NodeValueFn>(nv),
976 std::numeric_limits<T>::lowest(), Max_Op<T>(), std::move(sa))
977 {}
978
979 template <class NodeValueFn>
980 HLD_Max(const GT & g, NodeValueFn && nv, SA sa = SA())
981 : Base(g, std::forward<NodeValueFn>(nv),
982 std::numeric_limits<T>::lowest(), Max_Op<T>(), std::move(sa))
983 {}
984 };
985
994 template <class GT, typename T, class SA = Dft_Show_Arc<GT>>
995 struct HLD_Min : public Gen_HLD<GT, T, Min_Op<T>, SA>
996 {
998 using Node = typename GT::Node;
999
1000 template <class NodeValueFn>
1001 HLD_Min(const GT & g, Node * root, NodeValueFn && nv, SA sa = SA())
1002 : Base(g, root, std::forward<NodeValueFn>(nv),
1003 std::numeric_limits<T>::max(), Min_Op<T>(), std::move(sa))
1004 {}
1005
1006 template <class NodeValueFn>
1007 HLD_Min(const GT & g, NodeValueFn && nv, SA sa = SA())
1008 : Base(g, std::forward<NodeValueFn>(nv),
1009 std::numeric_limits<T>::max(), Min_Op<T>(), std::move(sa))
1010 {}
1011 };
1012
1013} // namespace Aleph
1014
1015#endif // HLD_H
Exception handling system with formatted messages for Aleph-w.
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
Definition ah-errors.H:250
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:579
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:639
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:139
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
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).
Heavy-Light Decomposition with segment tree for path/subtree queries.
Definition HLD.H:527
static constexpr size_t NONE
Definition HLD.H:533
void point_update_id(const size_t v, const T &new_value)
Point update by node ID: set value to new_value.
Definition HLD.H:811
size_t distance(const Node *u, const Node *v) const
Number of edges between two nodes in O(log n).
Definition HLD.H:867
T path_query(const Node *u, const Node *v) const
Path query by node pointers in O(log^2 n).
Definition HLD.H:731
T path_query_id(size_t u, size_t v) const
Path query by node IDs in O(log^2 n).
Definition HLD.H:699
size_t chain_head_id(const size_t id) const
Head of the chain containing node id.
Definition HLD.H:634
Node * node_of(const size_t id) const
Map an internal ID back to a Node pointer.
Definition HLD.H:615
size_t depth_of_id(const size_t id) const
Depth of node id from root.
Definition HLD.H:641
size_t subtree_size_of_id(const size_t id) const
Subtree size of node id.
Definition HLD.H:654
size_t num_chains() const noexcept
Number of heavy chains in the decomposition.
Definition HLD.H:681
T get_value(const Node *v) const
Current node value at node pointer v.
Definition HLD.H:921
size_t id_of(const Node *node) const
Map a Node pointer to its internal ID.
Definition HLD.H:621
size_t size() const noexcept
Total number of nodes in the tree.
Definition HLD.H:603
const Array< size_t > & position_array() const noexcept
Read-only access to the flat-position array.
Definition HLD.H:880
Node * lca(const Node *u, const Node *v) const
LCA query by node pointers in O(log n).
Definition HLD.H:849
size_t parent_id(const size_t id) const
Parent ID of node id, or NONE if root.
Definition HLD.H:667
Gen_HLD(const GT &g, Node *root, NodeValueFn &&node_value, const T &identity, Op oper=Op(), SA sa=SA())
Construct HLD from graph, root, and node value functor.
Definition HLD.H:580
void point_update(const Node *v, const T &new_value)
Point update by node pointer: set value to new_value.
Definition HLD.H:820
size_t position(const size_t id) const
HLD flat-array position of node id.
Definition HLD.H:627
size_t lca_id(size_t u, size_t v) const
LCA query by node IDs in O(log n).
Definition HLD.H:830
void ensure_not_empty(const char *where) const
Definition HLD.H:542
size_t root_id() const noexcept
Returns the internal ID of the root node.
Definition HLD.H:612
const Array< size_t > & subtree_size_array() const noexcept
Read-only access to the subtree-size array.
Definition HLD.H:902
void build_segment_tree(NodeValueFn &&node_value)
Definition HLD.H:549
T subtree_query(const Node *v) const
Subtree query by node pointer in O(log n).
Definition HLD.H:797
size_t subtree_size_of(const Node *node) const
Subtree size of node.
Definition HLD.H:661
T path_query_edges_id(size_t u, size_t v) const
Edge-weighted path query by node IDs in O(log^2 n).
Definition HLD.H:741
bool is_empty() const noexcept
Returns true if the tree has no nodes.
Definition HLD.H:606
size_t depth_of(const Node *node) const
Depth of node from root.
Definition HLD.H:648
Gen_Segment_Tree< T, Op > seg_
Definition HLD.H:538
const Array< size_t > & depth_array() const noexcept
Read-only access to the depth array.
Definition HLD.H:896
size_t n() const noexcept
Definition HLD.H:540
T subtree_query_id(const size_t v) const
Subtree query by node ID in O(log n).
Definition HLD.H:786
const Array< size_t > & parent_array() const noexcept
Read-only access to the parent array.
Definition HLD.H:908
typename GT::Node Node
Definition HLD.H:529
size_t distance_id(const size_t u, const size_t v) const
Number of edges between two nodes by IDs in O(log n).
Definition HLD.H:859
Gen_HLD(const GT &g, NodeValueFn &&node_value, const T &identity, Op oper=Op(), SA sa=SA())
Construct with first graph node as root.
Definition HLD.H:592
Node * root() const noexcept
Returns the root node.
Definition HLD.H:609
Node * parent_of(const Node *node) const
Parent of node, or nullptr if root.
Definition HLD.H:674
T get_value_at_id(const size_t id) const
Current node value at HLD position pos in the segment tree.
Definition HLD.H:914
T path_query_edges(const Node *u, const Node *v) const
Edge-weighted path query by node pointers.
Definition HLD.H:773
const Array< size_t > & chain_head_array() const noexcept
Read-only access to the chain-head array.
Definition HLD.H:890
Topology topology_
Definition HLD.H:535
Segment tree over an arbitrary associative binary operation.
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1206
const Array< size_t > & tout() const noexcept
Definition HLD.H:472
Array< Node * > id_to_node_
Definition HLD.H:137
typename GT::Node Node
Definition HLD.H:122
const Array< size_t > & chain_head() const noexcept
Definition HLD.H:470
void validate_id(const size_t id, const char *where) const
Definition HLD.H:493
const Array< size_t > & parent() const noexcept
Definition HLD.H:466
const Array< size_t > & tin() const noexcept
Definition HLD.H:471
HLD_Tree_Data(const GT &g, Node *root, SA sa=SA())
Definition HLD.H:450
const Array< size_t > & subtree_size() const noexcept
Definition HLD.H:468
static Pair_Key normalize_pair(size_t u, size_t v) noexcept
Definition HLD.H:153
Array< size_t > tout_
Definition HLD.H:149
Array< Array< size_t > > adjacency_
Definition HLD.H:140
size_t root_id() const noexcept
Definition HLD.H:463
const Array< Node * > & id_to_node() const noexcept
Definition HLD.H:465
Node * node_of(const size_t id) const
Definition HLD.H:487
Array< size_t > chain_head_
Definition HLD.H:147
Node * root() const noexcept
Definition HLD.H:462
size_t id_of(const Node *node) const
Definition HLD.H:475
static constexpr size_t NONE
Definition HLD.H:125
const Array< size_t > & depth() const noexcept
Definition HLD.H:467
Array< size_t > depth_
Definition HLD.H:142
MapOLhash< Node *, size_t > node_to_id_
Definition HLD.H:138
size_t size() const noexcept
Definition HLD.H:460
size_t num_chains() const noexcept
Definition HLD.H:473
bool is_empty() const noexcept
Definition HLD.H:461
void check_id(const size_t id, const char *where) const
Definition HLD.H:443
Array< size_t > subtree_size_
Definition HLD.H:143
const Array< size_t > & pos() const noexcept
Definition HLD.H:469
Array< size_t > parent_
Definition HLD.H:141
typename GT::Arc Arc
Definition HLD.H:123
std::pair< size_t, size_t > Pair_Key
Definition HLD.H:128
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:737
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:743
__gmp_expr< typename __gmp_resolve_expr< T, V >::value_type, __gmp_binary_expr< __gmp_expr< T, U >, __gmp_expr< V, W >, __gmp_max_function > > max(const __gmp_expr< T, U > &expr1, const __gmp_expr< V, W > &expr2)
Definition gmpfrxx.h:4110
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
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.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
STL namespace.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1164
HLD with path/subtree max queries.
Definition HLD.H:969
typename GT::Node Node
Definition HLD.H:971
HLD_Max(const GT &g, Node *root, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:974
HLD_Max(const GT &g, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:980
HLD with path/subtree min queries.
Definition HLD.H:996
HLD_Min(const GT &g, Node *root, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:1001
HLD_Min(const GT &g, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:1007
typename GT::Node Node
Definition HLD.H:998
HLD with path/subtree sum queries.
Definition HLD.H:942
typename GT::Node Node
Definition HLD.H:944
HLD_Sum(const GT &g, Node *root, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:947
HLD_Sum(const GT &g, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:953
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.
Functor returning the maximum of two values.
Functor returning the minimum of two values.
gsl_rng * r
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.
Segment trees for dynamic range queries with lazy propagation.
DynList< int > l