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 <ah-graph-concepts.H>
94
95# include <algorithm>
96# include <cstddef>
97# include <limits>
98# include <utility>
99
100# include <ah-errors.H>
101# include <tpl_array.H>
102# include <tpl_dynListStack.H>
103# include <tpl_dynMapOhash.H>
104# include <tpl_dynMapTree.H>
105# include <tpl_graph.H>
106# include <tpl_segment_tree.H>
107
108namespace Aleph
109{
110 namespace hld_detail
111 {
120 template <AlephGraph GT, ArcFilter<GT> SA>
122 {
123 public:
124 using Node = typename GT::Node;
125 using Arc = typename GT::Arc;
126
127 static constexpr size_t NONE = std::numeric_limits<size_t>::max();
128
129 private:
130 using Pair_Key = std::pair<size_t, size_t>;
131
132 const GT * graph_ = nullptr;
133 SA sa_;
134 Node * root_ = nullptr;
135 size_t root_id_ = NONE;
136
137 size_t n_ = 0;
138
141
146
147 // HLD-specific arrays
148 Array<size_t> pos_; // flat position in segment tree
149 Array<size_t> chain_head_; // head of the chain containing this node
150 Array<size_t> tin_; // entry time (same as pos_ for HLD)
151 Array<size_t> tout_; // exit time
152
153 size_t num_chains_ = 0;
154
155 static Pair_Key normalize_pair(size_t u, size_t v) noexcept
156 {
157 if (u > v)
158 std::swap(u, v);
159 return std::make_pair(u, v);
160 }
161
163 {
165
166 if (n_ == 0)
167 {
168 ah_domain_error_if(root_ != nullptr)
169 << "HLD_Tree_Data: root node provided but graph is empty";
170 return;
171 }
172
174 {
176 node_to_id_.swap(tmp);
177 }
178
179 size_t next_id = 0;
180 for (Node_Iterator<GT> it(*graph_); it.has_curr(); it.next_ne())
181 {
182 Node * p = it.get_curr();
183 id_to_node_(next_id) = p;
185 ++next_id;
186 }
187
189 << "HLD_Tree_Data: failed to index all graph nodes";
190
191 if (root_ == nullptr)
192 root_ = id_to_node_(0);
193
195 << "HLD_Tree_Data: root node does not belong to graph";
196
198 }
199
201 {
202 if (n_ == 0)
203 return;
204
205 adjacency_.empty();
206 adjacency_.reserve(n_);
207 for (size_t i = 0; i < n_; ++i)
208 adjacency_.append(Array<size_t>());
209
211 size_t edge_count = 0;
212
213 for (Arc_Iterator<GT, SA> it(*graph_, sa_); it.has_curr(); it.next_ne())
214 {
215 Arc * a = it.get_curr_ne();
216 Node * src = graph_->get_src_node(a);
217 Node * tgt = graph_->get_tgt_node(a);
218
219 const auto * src_item = node_to_id_.search(src);
220 const auto * tgt_item = node_to_id_.search(tgt);
221
222 ah_runtime_error_unless(src_item != nullptr and tgt_item != nullptr)
223 << "HLD_Tree_Data: arc endpoint is not indexed";
224
225 const size_t u = src_item->second;
226 const size_t v = tgt_item->second;
227
228 ah_domain_error_if(u == v)
229 << "HLD_Tree_Data: self-loop detected in filtered graph";
230
231 const Pair_Key key = normalize_pair(u, v);
232 ah_domain_error_if(unique_edges.search(key) != nullptr)
233 << "HLD_Tree_Data: parallel/duplicate edge detected in filtered graph";
234
235 unique_edges.insert(key, 1);
236 ++edge_count;
237 }
238
240 << "HLD_Tree_Data: filtered graph is not a tree (expected "
241 << (n_ - 1) << " edges, got " << edge_count << ")";
242
244 it.has_curr(); it.next_ne())
245 {
246 const auto & [fst, snd] = it.get_curr();
247 const size_t u = fst.first;
248 const size_t v = fst.second;
249 adjacency_(u).append(v);
250 adjacency_(v).append(u);
251 }
252 }
253
255 {
256 if (n_ == 0)
257 return;
258
262
263 for (size_t i = 0; i < n_; ++i)
264 {
265 parent_(i) = NONE;
266 subtree_size_(i) = 1;
267 }
268
270 for (size_t i = 0; i < n_; ++i)
271 visited(i) = 0;
272
273 struct Frame
274 {
275 size_t node;
276 size_t parent;
277 size_t next_child;
278 };
279
281
282 size_t visited_count = 1;
283 visited(root_id_) = 1;
284 depth_(root_id_) = 0;
286
287 stack.push({root_id_, NONE, 0});
288
289 while (not stack.is_empty())
290 {
291 auto & fr = stack.top();
292
293 if (fr.next_child == adjacency_(fr.node).size())
294 {
295 // All children processed; accumulate size into parent.
296 // Save fr.node before pop() invalidates the reference.
297 const size_t done = fr.node;
298 (void) stack.pop();
299 if (not stack.is_empty())
300 subtree_size_(stack.top().node) += subtree_size_(done);
301 continue;
302 }
303
304 const size_t nxt = adjacency_(fr.node)(fr.next_child++);
305 if (nxt == fr.parent)
306 continue;
307
308 ah_domain_error_if(visited(nxt))
309 << "HLD_Tree_Data: filtered graph is not acyclic";
310
311 visited(nxt) = 1;
313
314 parent_(nxt) = fr.node;
315 depth_(nxt) = depth_(fr.node) + 1;
316
317 stack.push({nxt, fr.node, 0});
318 }
319
321 << "HLD_Tree_Data: filtered graph is not connected";
322 }
323
325 {
326 if (n_ == 0)
327 return;
328
329 for (size_t u = 0; u < n_; ++u)
330 {
331 auto & adj = adjacency_(u);
332 if (adj.size() <= 1)
333 continue;
334
335 // Find the child with the largest subtree_size
336 size_t best_idx = NONE;
337 size_t best_size = 0;
338
339 for (size_t i = 0; i < adj.size(); ++i)
340 {
341 const size_t v = adj(i);
342 if (v == parent_(u))
343 continue;
344 if (subtree_size_(v) > best_size)
345 {
347 best_idx = i;
348 }
349 }
350
351 if (best_idx == NONE)
352 continue;
353
354 // Swap the heavy child to position 0 (or the first non-parent)
355 // Find the first non-parent position
356 size_t first_child_pos = 0;
357 if (adj(0) == parent_(u))
358 first_child_pos = 1;
359
361 std::swap(adj(best_idx), adj(first_child_pos));
362 }
363 }
364
366 {
367 if (n_ == 0)
368 return;
369
374
375 struct Frame
376 {
377 size_t node;
378 size_t parent;
379 size_t next_child;
380 size_t head;
381 };
382
384
385 size_t timer = 0;
386 num_chains_ = 0;
387
388 // Root starts a new chain
392 ++timer;
393 ++num_chains_;
394
395 stack.push({root_id_, NONE, 0, root_id_});
396
397 while (not stack.is_empty())
398 {
399 auto & fr = stack.top();
400
401 if (fr.next_child == adjacency_(fr.node).size())
402 {
403 tout_(fr.node) = timer - 1;
404 (void) stack.pop();
405 continue;
406 }
407
408 const size_t nxt = adjacency_(fr.node)(fr.next_child);
409 ++fr.next_child;
410
411 if (nxt == fr.parent)
412 continue;
413
414 // Determine if this is a heavy or light child
415 // The heavy child is the first non-parent child in adjacency
416 // (after reordering)
417 bool is_heavy = false;
418 {
419 const auto & adj = adjacency_(fr.node);
420 size_t first_child_pos = 0;
421 if (adj.size() > 0 and adj(0) == fr.parent)
422 first_child_pos = 1;
423 if (first_child_pos < adj.size() and adj(first_child_pos) == nxt)
424 is_heavy = true;
425 }
426
427 if (is_heavy)
428 {
429 chain_head_(nxt) = fr.head;
430 }
431 else
432 {
434 ++num_chains_;
435 }
436
437 pos_(nxt) = timer;
438 tin_(nxt) = timer;
439 ++timer;
440
441 stack.push({nxt, fr.node, 0, chain_head_(nxt)});
442 }
443 }
444
445 void check_id(const size_t id, const char * where) const
446 {
448 << where << ": id=" << id << " is out of range [0, " << n_ << ")";
449 }
450
451 public:
452 HLD_Tree_Data(const GT & g, Node * root, SA sa = SA())
453 : graph_(&g), sa_(std::move(sa)), root_(root)
454 {
455 index_nodes();
460 }
461
462 [[nodiscard]] size_t size() const noexcept { return n_; }
463 [[nodiscard]] bool is_empty() const noexcept { return n_ == 0; }
464 [[nodiscard]] Node * root() const noexcept { return root_; }
465 [[nodiscard]] size_t root_id() const noexcept { return root_id_; }
466
471 [[nodiscard]] const Array<size_t> & pos() const noexcept { return pos_; }
473 [[nodiscard]] const Array<size_t> & tin() const noexcept { return tin_; }
474 [[nodiscard]] const Array<size_t> & tout() const noexcept { return tout_; }
476
477 [[nodiscard]] size_t id_of(const Node * node) const
478 {
479 ah_invalid_argument_if(node == nullptr)
480 << "HLD_Tree_Data::id_of: null node";
481
482 const auto * item = node_to_id_.search(const_cast<Node *>(node));
483 ah_domain_error_if(item == nullptr)
484 << "HLD_Tree_Data::id_of: node does not belong to graph";
485
486 return item->second;
487 }
488
489 [[nodiscard]] Node * node_of(const size_t id) const
490 {
491 check_id(id, "HLD_Tree_Data::node_of");
492 return id_to_node_(id);
493 }
494
495 void validate_id(const size_t id, const char * where) const
496 {
497 check_id(id, where);
498 }
499 };
500 } // namespace hld_detail
501
502
526 template <AlephGraph GT, typename T, class Op, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
527 requires SegmentTreeOp<Op, T>
529 {
530 public:
531 using Node = typename GT::Node;
532
533 private:
535 static constexpr size_t NONE = Topology::NONE;
536
539 Op op_;
541
542 [[nodiscard]] size_t n() const noexcept { return topology_.size(); }
543
544 void ensure_not_empty(const char * where) const
545 {
546 ah_domain_error_if(is_empty()) << where << ": tree is empty";
547 }
548
550 template <class NodeValueFn>
552 {
553 if (is_empty())
554 return;
555
556 auto flat = Array<T>::create(n());
557 for (size_t i = 0; i < n(); ++i)
558 flat(i) = identity_;
559
560 for (size_t id = 0; id < n(); ++id)
561 {
562 const size_t p = topology_.pos()(id);
564 }
565
567 seg_.swap(real_seg);
568 }
569
570 public:
581 template <class NodeValueFn>
583 const T & identity, Op oper = Op(), SA sa = SA())
584 : topology_(g, root, std::move(sa)),
585 identity_(identity),
586 op_(oper),
587 seg_(1, identity, identity, oper)
588 {
589 build_segment_tree(std::forward<NodeValueFn>(node_value));
590 }
591
593 template <class NodeValueFn>
595 const T & identity, Op oper = Op(), SA sa = SA())
596 : topology_(g, nullptr, std::move(sa)),
597 identity_(identity),
598 op_(oper),
599 seg_(1, identity, identity, oper)
600 {
601 build_segment_tree(std::forward<NodeValueFn>(node_value));
602 }
603
605 [[nodiscard]] size_t size() const noexcept { return topology_.size(); }
606
609
612
614 [[nodiscard]] size_t root_id() const noexcept { return topology_.root_id(); }
615
617 [[nodiscard]] Node * node_of(const size_t id) const
618 {
619 return topology_.node_of(id);
620 }
621
623 [[nodiscard]] size_t id_of(const Node * node) const
624 {
625 return topology_.id_of(node);
626 }
627
629 [[nodiscard]] size_t position(const size_t id) const
630 {
631 topology_.validate_id(id, "Gen_HLD::position");
632 return topology_.pos()(id);
633 }
634
636 [[nodiscard]] size_t chain_head_id(const size_t id) const
637 {
638 topology_.validate_id(id, "Gen_HLD::chain_head_id");
639 return topology_.chain_head()(id);
640 }
641
643 [[nodiscard]] size_t depth_of_id(const size_t id) const
644 {
645 topology_.validate_id(id, "Gen_HLD::depth_of_id");
646 return topology_.depth()(id);
647 }
648
650 [[nodiscard]] size_t depth_of(const Node * node) const
651 {
652 return depth_of_id(id_of(node));
653 }
654
656 [[nodiscard]] size_t subtree_size_of_id(const size_t id) const
657 {
658 topology_.validate_id(id, "Gen_HLD::subtree_size_of_id");
659 return topology_.subtree_size()(id);
660 }
661
663 [[nodiscard]] size_t subtree_size_of(const Node * node) const
664 {
665 return subtree_size_of_id(id_of(node));
666 }
667
669 [[nodiscard]] size_t parent_id(const size_t id) const
670 {
671 topology_.validate_id(id, "Gen_HLD::parent_id");
672 return topology_.parent()(id);
673 }
674
676 [[nodiscard]] Node * parent_of(const Node * node) const
677 {
678 const size_t pid = parent_id(id_of(node));
679 return pid == NONE ? nullptr : node_of(pid);
680 }
681
684 {
685 return topology_.num_chains();
686 }
687
688 // ------------------------------------------------------------------
689 // Path queries
690 // ------------------------------------------------------------------
691
701 [[nodiscard]] T path_query_id(size_t u, size_t v) const
702 {
703 ensure_not_empty("Gen_HLD::path_query_id");
704 topology_.validate_id(u, "Gen_HLD::path_query_id");
705 topology_.validate_id(v, "Gen_HLD::path_query_id");
706
707 T result = identity_;
708
709 while (topology_.chain_head()(u) != topology_.chain_head()(v))
710 {
711 // Move the deeper chain head up
712 if (topology_.depth()(topology_.chain_head()(u)) <
714 std::swap(u, v);
715
716 // Query the segment from chain_head(u) to u
717 const size_t head = topology_.chain_head()(u);
718 result = op_(result, seg_.query(topology_.pos()(head),
719 topology_.pos()(u)));
720 u = topology_.parent()(head);
721 }
722
723 // u and v are now on the same chain
724 if (topology_.depth()(u) > topology_.depth()(v))
725 std::swap(u, v);
726
727 result = op_(result, seg_.query(topology_.pos()(u),
728 topology_.pos()(v)));
729 return result;
730 }
731
733 [[nodiscard]] T path_query(const Node * u, const Node * v) const
734 {
735 return path_query_id(id_of(u), id_of(v));
736 }
737
743 [[nodiscard]] T path_query_edges_id(size_t u, size_t v) const
744 {
745 ensure_not_empty("Gen_HLD::path_query_edges_id");
746 topology_.validate_id(u, "Gen_HLD::path_query_edges_id");
747 topology_.validate_id(v, "Gen_HLD::path_query_edges_id");
748
749 T result = identity_;
750
751 while (topology_.chain_head()(u) != topology_.chain_head()(v))
752 {
753 if (topology_.depth()(topology_.chain_head()(u)) <
755 std::swap(u, v);
756
757 const size_t head = topology_.chain_head()(u);
758 result = op_(result, seg_.query(topology_.pos()(head),
759 topology_.pos()(u)));
760 u = topology_.parent()(head);
761 }
762
763 if (topology_.depth()(u) > topology_.depth()(v))
764 std::swap(u, v);
765
766 // Skip the LCA node (u) for edge-weighted queries
767 if (u != v)
768 result = op_(result, seg_.query(topology_.pos()(u) + 1,
769 topology_.pos()(v)));
770
771 return result;
772 }
773
775 [[nodiscard]] T path_query_edges(const Node * u, const Node * v) const
776 {
777 return path_query_edges_id(id_of(u), id_of(v));
778 }
779
780 // ------------------------------------------------------------------
781 // Subtree queries
782 // ------------------------------------------------------------------
783
788 [[nodiscard]] T subtree_query_id(const size_t v) const
789 {
790 ensure_not_empty("Gen_HLD::subtree_query_id");
791 topology_.validate_id(v, "Gen_HLD::subtree_query_id");
792
793 const size_t l = topology_.pos()(v);
794 const size_t r = l + topology_.subtree_size()(v) - 1;
795 return seg_.query(l, r);
796 }
797
799 [[nodiscard]] T subtree_query(const Node * v) const
800 {
801 return subtree_query_id(id_of(v));
802 }
803
804 // ------------------------------------------------------------------
805 // Point update
806 // ------------------------------------------------------------------
807
813 void point_update_id(const size_t v, const T & new_value)
814 {
815 ensure_not_empty("Gen_HLD::point_update_id");
816 topology_.validate_id(v, "Gen_HLD::point_update_id");
817
818 seg_.set(topology_.pos()(v), new_value);
819 }
820
822 void point_update(const Node * v, const T & new_value)
823 {
825 }
826
827 // ------------------------------------------------------------------
828 // LCA queries (free from chain walk)
829 // ------------------------------------------------------------------
830
832 [[nodiscard]] size_t lca_id(size_t u, size_t v) const
833 {
834 ensure_not_empty("Gen_HLD::lca_id");
835 topology_.validate_id(u, "Gen_HLD::lca_id");
836 topology_.validate_id(v, "Gen_HLD::lca_id");
837
838 while (topology_.chain_head()(u) != topology_.chain_head()(v))
839 {
840 if (topology_.depth()(topology_.chain_head()(u)) <
842 std::swap(u, v);
843
845 }
846
847 return topology_.depth()(u) <= topology_.depth()(v) ? u : v;
848 }
849
851 [[nodiscard]] Node * lca(const Node * u, const Node * v) const
852 {
853 return node_of(lca_id(id_of(u), id_of(v)));
854 }
855
856 // ------------------------------------------------------------------
857 // Distance queries
858 // ------------------------------------------------------------------
859
861 [[nodiscard]] size_t distance_id(const size_t u, const size_t v) const
862 {
863 const size_t a = lca_id(u, v);
864 return topology_.depth()(u) + topology_.depth()(v)
865 - 2 * topology_.depth()(a);
866 }
867
869 [[nodiscard]] size_t distance(const Node * u, const Node * v) const
870 {
871 return distance_id(id_of(u), id_of(v));
872 }
873
874 // ------------------------------------------------------------------
875 // Decomposition accessors (for power users)
876 // ------------------------------------------------------------------
877
883 {
884 return topology_.pos();
885 }
886
896
899 {
900 return topology_.depth();
901 }
902
908
911 {
912 return topology_.parent();
913 }
914
916 [[nodiscard]] T get_value_at_id(const size_t id) const
917 {
918 topology_.validate_id(id, "Gen_HLD::get_value_at_id");
919 return seg_.get(topology_.pos()(id));
920 }
921
923 [[nodiscard]] T get_value(const Node * v) const
924 {
925 return get_value_at_id(id_of(v));
926 }
927 };
928
929
930 // ====================================================================
931 // Convenience aliases
932 // ====================================================================
933
942 template <AlephGraph GT, typename T, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
943 struct HLD_Sum : public Gen_HLD<GT, T, Aleph::plus<T>, SA>
944 {
946 using Node = typename GT::Node;
947
948 template <class NodeValueFn>
949 HLD_Sum(const GT & g, Node * root, NodeValueFn && nv, SA sa = SA())
950 : Base(g, root, std::forward<NodeValueFn>(nv),
951 T(), Aleph::plus<T>(), std::move(sa))
952 {}
953
954 template <class NodeValueFn>
955 HLD_Sum(const GT & g, NodeValueFn && nv, SA sa = SA())
956 : Base(g, std::forward<NodeValueFn>(nv),
957 T(), Aleph::plus<T>(), std::move(sa))
958 {}
959 };
960
969 template <AlephGraph GT, typename T, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
970 struct HLD_Max : public Gen_HLD<GT, T, Max_Op<T>, SA>
971 {
973 using Node = typename GT::Node;
974
975 template <class NodeValueFn>
976 HLD_Max(const GT & g, Node * root, NodeValueFn && nv, SA sa = SA())
977 : Base(g, root, std::forward<NodeValueFn>(nv),
978 std::numeric_limits<T>::lowest(), Max_Op<T>(), std::move(sa))
979 {}
980
981 template <class NodeValueFn>
982 HLD_Max(const GT & g, NodeValueFn && nv, SA sa = SA())
983 : Base(g, std::forward<NodeValueFn>(nv),
984 std::numeric_limits<T>::lowest(), Max_Op<T>(), std::move(sa))
985 {}
986 };
987
996 template <AlephGraph GT, typename T, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
997 struct HLD_Min : public Gen_HLD<GT, T, Min_Op<T>, SA>
998 {
1000 using Node = typename GT::Node;
1001
1002 template <class NodeValueFn>
1003 HLD_Min(const GT & g, Node * root, NodeValueFn && nv, SA sa = SA())
1004 : Base(g, root, std::forward<NodeValueFn>(nv),
1005 std::numeric_limits<T>::max(), Min_Op<T>(), std::move(sa))
1006 {}
1007
1008 template <class NodeValueFn>
1009 HLD_Min(const GT & g, NodeValueFn && nv, SA sa = SA())
1010 : Base(g, std::forward<NodeValueFn>(nv),
1011 std::numeric_limits<T>::max(), Min_Op<T>(), std::move(sa))
1012 {}
1013 };
1014
1015} // namespace Aleph
1016
1017#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:255
#define ah_out_of_range_error_if(C)
Throws std::out_of_range if condition holds.
Definition ah-errors.H:584
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:527
#define ah_invalid_argument_if(C)
Throws std::invalid_argument if condition holds.
Definition ah-errors.H:644
C++20 concepts for the protocol shared by graph algorithms.
Simple dynamic array with automatic resizing and functional operations.
Definition tpl_array.H:138
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:196
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:529
static constexpr size_t NONE
Definition HLD.H:535
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:813
size_t distance(const Node *u, const Node *v) const
Number of edges between two nodes in O(log n).
Definition HLD.H:869
T path_query(const Node *u, const Node *v) const
Path query by node pointers in O(log^2 n).
Definition HLD.H:733
T path_query_id(size_t u, size_t v) const
Path query by node IDs in O(log^2 n).
Definition HLD.H:701
size_t chain_head_id(const size_t id) const
Head of the chain containing node id.
Definition HLD.H:636
Node * node_of(const size_t id) const
Map an internal ID back to a Node pointer.
Definition HLD.H:617
size_t depth_of_id(const size_t id) const
Depth of node id from root.
Definition HLD.H:643
size_t subtree_size_of_id(const size_t id) const
Subtree size of node id.
Definition HLD.H:656
size_t num_chains() const noexcept
Number of heavy chains in the decomposition.
Definition HLD.H:683
T get_value(const Node *v) const
Current node value at node pointer v.
Definition HLD.H:923
size_t id_of(const Node *node) const
Map a Node pointer to its internal ID.
Definition HLD.H:623
size_t size() const noexcept
Total number of nodes in the tree.
Definition HLD.H:605
const Array< size_t > & position_array() const noexcept
Read-only access to the flat-position array.
Definition HLD.H:882
Node * lca(const Node *u, const Node *v) const
LCA query by node pointers in O(log n).
Definition HLD.H:851
size_t parent_id(const size_t id) const
Parent ID of node id, or NONE if root.
Definition HLD.H:669
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:582
void point_update(const Node *v, const T &new_value)
Point update by node pointer: set value to new_value.
Definition HLD.H:822
size_t position(const size_t id) const
HLD flat-array position of node id.
Definition HLD.H:629
size_t lca_id(size_t u, size_t v) const
LCA query by node IDs in O(log n).
Definition HLD.H:832
void ensure_not_empty(const char *where) const
Definition HLD.H:544
size_t root_id() const noexcept
Returns the internal ID of the root node.
Definition HLD.H:614
const Array< size_t > & subtree_size_array() const noexcept
Read-only access to the subtree-size array.
Definition HLD.H:904
void build_segment_tree(NodeValueFn &&node_value)
Definition HLD.H:551
T subtree_query(const Node *v) const
Subtree query by node pointer in O(log n).
Definition HLD.H:799
size_t subtree_size_of(const Node *node) const
Subtree size of node.
Definition HLD.H:663
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:743
bool is_empty() const noexcept
Returns true if the tree has no nodes.
Definition HLD.H:608
size_t depth_of(const Node *node) const
Depth of node from root.
Definition HLD.H:650
Gen_Segment_Tree< T, Op > seg_
Definition HLD.H:540
const Array< size_t > & depth_array() const noexcept
Read-only access to the depth array.
Definition HLD.H:898
size_t n() const noexcept
Definition HLD.H:542
T subtree_query_id(const size_t v) const
Subtree query by node ID in O(log n).
Definition HLD.H:788
const Array< size_t > & parent_array() const noexcept
Read-only access to the parent array.
Definition HLD.H:910
typename GT::Node Node
Definition HLD.H:531
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:861
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:594
Node * root() const noexcept
Returns the root node.
Definition HLD.H:611
Node * parent_of(const Node *node) const
Parent of node, or nullptr if root.
Definition HLD.H:676
T get_value_at_id(const size_t id) const
Current node value at HLD position pos in the segment tree.
Definition HLD.H:916
T path_query_edges(const Node *u, const Node *v) const
Edge-weighted path query by node pointers.
Definition HLD.H:775
const Array< size_t > & chain_head_array() const noexcept
Read-only access to the chain-head array.
Definition HLD.H:892
Topology topology_
Definition HLD.H:537
Segment tree over an arbitrary associative binary operation.
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1207
const Array< size_t > & tout() const noexcept
Definition HLD.H:474
Array< Node * > id_to_node_
Definition HLD.H:139
typename GT::Node Node
Definition HLD.H:124
const Array< size_t > & chain_head() const noexcept
Definition HLD.H:472
void validate_id(const size_t id, const char *where) const
Definition HLD.H:495
const Array< size_t > & parent() const noexcept
Definition HLD.H:468
const Array< size_t > & tin() const noexcept
Definition HLD.H:473
HLD_Tree_Data(const GT &g, Node *root, SA sa=SA())
Definition HLD.H:452
const Array< size_t > & subtree_size() const noexcept
Definition HLD.H:470
static Pair_Key normalize_pair(size_t u, size_t v) noexcept
Definition HLD.H:155
Array< size_t > tout_
Definition HLD.H:151
Array< Array< size_t > > adjacency_
Definition HLD.H:142
size_t root_id() const noexcept
Definition HLD.H:465
const Array< Node * > & id_to_node() const noexcept
Definition HLD.H:467
Node * node_of(const size_t id) const
Definition HLD.H:489
Array< size_t > chain_head_
Definition HLD.H:149
Node * root() const noexcept
Definition HLD.H:464
size_t id_of(const Node *node) const
Definition HLD.H:477
static constexpr size_t NONE
Definition HLD.H:127
const Array< size_t > & depth() const noexcept
Definition HLD.H:469
Array< size_t > depth_
Definition HLD.H:144
MapOLhash< Node *, size_t > node_to_id_
Definition HLD.H:140
size_t size() const noexcept
Definition HLD.H:462
size_t num_chains() const noexcept
Definition HLD.H:475
bool is_empty() const noexcept
Definition HLD.H:463
void check_id(const size_t id, const char *where) const
Definition HLD.H:445
Array< size_t > subtree_size_
Definition HLD.H:145
const Array< size_t > & pos() const noexcept
Definition HLD.H:471
Array< size_t > parent_
Definition HLD.H:143
typename GT::Arc Arc
Definition HLD.H:125
std::pair< size_t, size_t > Pair_Key
Definition HLD.H:130
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:779
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:737
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:785
__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:4121
size_t blossom_maximum_cardinality_matching(const GT &g, DynDlist< typename GT::Arc * > &matching, SA sa=SA())
Alias of compute_maximum_cardinality_general_matching().
Definition Blossom.H:466
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
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:1165
HLD with path/subtree max queries.
Definition HLD.H:971
typename GT::Node Node
Definition HLD.H:973
HLD_Max(const GT &g, Node *root, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:976
HLD_Max(const GT &g, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:982
HLD with path/subtree min queries.
Definition HLD.H:998
HLD_Min(const GT &g, Node *root, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:1003
HLD_Min(const GT &g, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:1009
typename GT::Node Node
Definition HLD.H:1000
HLD with path/subtree sum queries.
Definition HLD.H:944
typename GT::Node Node
Definition HLD.H:946
HLD_Sum(const GT &g, Node *root, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:949
HLD_Sum(const GT &g, NodeValueFn &&nv, SA sa=SA())
Definition HLD.H:955
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