Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
LCA.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
93#ifndef LCA_H
94#define LCA_H
95
96# include <ah-graph-concepts.H>
97
98#include <algorithm>
99#include <bit>
100#include <cstddef>
101#include <limits>
102#include <utility>
103
104#include <ah-errors.H>
105#include <tpl_array.H>
106#include <tpl_dynListStack.H>
107#include <tpl_dynMapOhash.H>
108#include <tpl_dynMapTree.H>
109#include <tpl_graph.H>
110#include <tpl_sparse_table.H>
111
112namespace Aleph {
113namespace lca_detail {
125template <AlephGraph GT, ArcFilter<GT> SA>
127{
128public:
129 using Node = typename GT::Node;
130 using Arc = typename GT::Arc;
131
132 static constexpr size_t NONE = std::numeric_limits<size_t>::max();
133
134private:
135 using Pair_Key = std::pair<size_t, size_t>;
136
137 const GT *graph_ = nullptr;
138 SA sa_;
139 Node *root_ = nullptr;
140 size_t root_id_ = NONE;
141
142 size_t n_ = 0;
143
146
154 size_t euler_size_ = 0;
155
156 static Pair_Key normalize_pair(size_t u, size_t v) noexcept
157 {
158 if (u > v)
159 std::swap(u, v);
160 return std::make_pair(u, v);
161 }
162
164 {
166
167 if (n_ == 0)
168 {
169 ah_domain_error_if(root_ != nullptr)
170 << "Rooted_Tree_Data: root node provided but graph is empty";
171 return;
172 }
173
175 {
177 node_to_id_.swap(tmp);
178 }
179
180 size_t next_id = 0;
181 for (Node_Iterator<GT> it(*graph_); it.has_curr(); it.next_ne())
182 {
183 Node *p = it.get_curr();
184 id_to_node_(next_id) = p;
186 ++next_id;
187 }
188
189 ah_runtime_error_unless(next_id == n_) << "Rooted_Tree_Data: failed to index all graph nodes";
190
191 if (root_ == nullptr)
192 root_ = id_to_node_(0);
193
195 << "Rooted_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 << "Rooted_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) << "Rooted_Tree_Data: self-loop detected in filtered graph";
229
230 const Pair_Key key = normalize_pair(u, v);
231 ah_domain_error_if(unique_edges.search(key) != nullptr)
232 << "Rooted_Tree_Data: parallel/duplicate edge detected in filtered graph";
233
234 unique_edges.insert(key, 1);
235 ++edge_count;
236 }
237
239 << "Rooted_Tree_Data: filtered graph is not a tree (expected " << (n_ - 1) << " edges, got "
240 << edge_count << ")";
241
242 for (typename DynMapTree<Pair_Key, char>::Iterator it(unique_edges); 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
263
264 for (size_t i = 0; i < n_; ++i)
265 parent_(i) = NONE;
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 timer = 0;
281 size_t visited_count = 1;
282
283 visited(root_id_) = 1;
284 depth_(root_id_) = 0;
286 tin_(root_id_) = timer++;
287
288 euler_size_ = 0;
291
292 stack.push({root_id_, NONE, 0});
293
294 while (not stack.is_empty())
295 {
296 auto &fr = stack.top();
297
298 if (fr.next_child == adjacency_(fr.node).size())
299 {
300 tout_(fr.node) = timer - 1;
301 (void) stack.pop();
302 if (not stack.is_empty())
303 euler_(euler_size_++) = stack.top().node;
304 continue;
305 }
306
307 const size_t nxt = adjacency_(fr.node)(fr.next_child++);
308 if (nxt == fr.parent)
309 continue;
310
311 ah_domain_error_if(visited(nxt)) << "Rooted_Tree_Data: filtered graph is not acyclic";
312
313 visited(nxt) = 1;
315
316 parent_(nxt) = fr.node;
317 depth_(nxt) = depth_(fr.node) + 1;
318 tin_(nxt) = timer++;
319
322
323 stack.push({nxt, fr.node, 0});
324 }
325
326 ah_domain_error_if(visited_count != n_) << "Rooted_Tree_Data: filtered graph is not connected";
327
329 << "Rooted_Tree_Data: unexpected Euler tour size";
330 }
331
332 void check_id(const size_t id, const char *where) const
333 {
335 << where << ": id=" << id << " is out of range [0, " << n_ << ")";
336 }
337
338public:
339 Rooted_Tree_Data(const GT &g, Node *root, SA sa = SA())
340 : graph_(&g), sa_(std::move(sa)), root_(root)
341 {
342 index_nodes();
345 }
346
348 {
349 return n_;
350 }
352 {
353 return n_ == 0;
354 }
356 {
357 return root_;
358 }
360 {
361 return root_id_;
362 }
363
365 {
366 return id_to_node_;
367 }
369 {
370 return parent_;
371 }
373 {
374 return depth_;
375 }
377 {
378 return tin_;
379 }
381 {
382 return tout_;
383 }
385 {
386 return first_;
387 }
389 {
390 return euler_;
391 }
393 {
394 return euler_size_;
395 }
396
397 [[nodiscard]] size_t id_of(const Node *node) const
398 {
399 ah_invalid_argument_if(node == nullptr) << "Rooted_Tree_Data::id_of: null node";
400
401 const auto *item = node_to_id_.search(const_cast<Node *>(node));
402 ah_domain_error_if(item == nullptr) << "Rooted_Tree_Data::id_of: node does not belong to graph";
403
404 return item->second;
405 }
406
407 [[nodiscard]] Node *node_of(const size_t id) const
408 {
409 check_id(id, "Rooted_Tree_Data::node_of");
410 return id_to_node_(id);
411 }
412
413 void validate_id(const size_t id, const char *where) const
414 {
415 check_id(id, where);
416 }
417
418 [[nodiscard]] bool is_ancestor(const size_t u, const size_t v) const
419 {
420 check_id(u, "Rooted_Tree_Data::is_ancestor");
421 check_id(v, "Rooted_Tree_Data::is_ancestor");
422 return tin_(u) <= tin_(v) and tout_(v) <= tout_(u);
423 }
424};
425
427{
428 size_t depth = 0;
429 size_t node = 0;
430};
431
433{
434 Depth_Node operator()(const Depth_Node &a, const Depth_Node &b) const noexcept
435 {
436 if (a.depth < b.depth)
437 return a;
438 if (b.depth < a.depth)
439 return b;
440 return (a.node <= b.node) ? a : b;
441 }
442};
443} // namespace lca_detail
444
465template <AlephGraph GT, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
467{
468public:
469 using Node = typename GT::Node;
470
471private:
473 static constexpr size_t NONE = Topology::NONE;
474
476 size_t levels_ = 0;
477 Array<size_t> up_; // flattened: up_[k * n + v]
478
480 {
481 return topology_.size();
482 }
483
484 size_t &up_at(const size_t k, const size_t v) noexcept
485 {
486 return up_(k * n() + v);
487 }
488
489 [[nodiscard]] size_t up_at(const size_t k, const size_t v) const noexcept
490 {
491 return up_(k * n() + v);
492 }
493
494 void ensure_not_empty(const char *where) const
495 {
496 ah_domain_error_if(is_empty()) << where << ": tree is empty";
497 }
498
501 {
502 if (is_empty())
503 return;
504
505 levels_ = static_cast<size_t>(std::bit_width(n()));
506
508 for (size_t i = 0; i < levels_ * n(); ++i)
509 up_(i) = NONE;
510
511 for (size_t v = 0; v < n(); ++v)
512 up_at(0, v) = topology_.parent()(v);
513
514 for (size_t k = 1; k < levels_; ++k)
515 for (size_t v = 0; v < n(); ++v)
516 {
517 const size_t mid = up_at(k - 1, v);
518 up_at(k, v) = (mid == NONE) ? NONE : up_at(k - 1, mid);
519 }
520 }
521
523 [[nodiscard]] size_t lift(size_t v, size_t delta) const
524 {
525 for (size_t k = 0; k < levels_ and delta > 0 and v != NONE; ++k)
526 if ((delta >> k) & 1U)
527 v = up_at(k, v);
528 return v;
529 }
530
531public:
541 Gen_Binary_Lifting_LCA(const GT &g, Node *root, SA sa = SA()) : topology_(g, root, std::move(sa))
542 {
544 }
545
551 Gen_Binary_Lifting_LCA(const GT &g, SA sa = SA()) : topology_(g, nullptr, std::move(sa))
552 {
554 }
555
558 {
559 return topology_.size();
560 }
561
564 {
565 return topology_.is_empty();
566 }
567
570 {
571 return topology_.root();
572 }
573
576 {
577 return topology_.root_id();
578 }
579
582 {
583 return levels_;
584 }
585
587 [[nodiscard]] Node *node_of(const size_t id) const
588 {
589 return topology_.node_of(id);
590 }
591
593 [[nodiscard]] size_t id_of(const Node *node) const
594 {
595 return topology_.id_of(node);
596 }
597
599 [[nodiscard]] size_t depth_of_id(const size_t id) const
600 {
601 topology_.validate_id(id, "Gen_Binary_Lifting_LCA::depth_of_id");
602 return topology_.depth()(id);
603 }
604
606 [[nodiscard]] size_t depth_of(const Node *node) const
607 {
608 return depth_of_id(id_of(node));
609 }
610
612 [[nodiscard]] size_t parent_id(const size_t id) const
613 {
614 topology_.validate_id(id, "Gen_Binary_Lifting_LCA::parent_id");
615 return topology_.parent()(id);
616 }
617
619 [[nodiscard]] Node *parent_of(const Node *node) const
620 {
621 const size_t pid = parent_id(id_of(node));
622 return pid == NONE ? nullptr : node_of(pid);
623 }
624
626 [[nodiscard]] bool is_ancestor_id(const size_t u, const size_t v) const
627 {
628 return topology_.is_ancestor(u, v);
629 }
630
632 [[nodiscard]] bool is_ancestor(const Node *u, const Node *v) const
633 {
634 return is_ancestor_id(id_of(u), id_of(v));
635 }
636
643 [[nodiscard]] size_t kth_ancestor_id(const size_t id, const size_t k) const
644 {
645 topology_.validate_id(id, "Gen_Binary_Lifting_LCA::kth_ancestor_id");
646 if (k > topology_.depth()(id))
647 return NONE;
648 return lift(id, k);
649 }
650
655 [[nodiscard]] Node *kth_ancestor(const Node *node, const size_t k) const
656 {
657 const size_t a = kth_ancestor_id(id_of(node), k);
658 return a == NONE ? nullptr : node_of(a);
659 }
660
662 [[nodiscard]] size_t lca_id(size_t u, size_t v) const
663 {
664 ensure_not_empty("Gen_Binary_Lifting_LCA::lca_id");
665 topology_.validate_id(u, "Gen_Binary_Lifting_LCA::lca_id");
666 topology_.validate_id(v, "Gen_Binary_Lifting_LCA::lca_id");
667
668 if (topology_.depth()(u) < topology_.depth()(v))
669 std::swap(u, v);
670
671 u = lift(u, topology_.depth()(u) - topology_.depth()(v));
672 if (u == v)
673 return u;
674
675 for (size_t k = levels_; k-- > 0;)
676 {
677 const size_t uu = up_at(k, u);
678 const size_t vv = up_at(k, v);
679 if (uu != vv)
680 {
681 u = uu;
682 v = vv;
683 }
684 }
685
686 const size_t ret = topology_.parent()(u);
688 << "Gen_Binary_Lifting_LCA::lca_id: internal invalid parent";
689 return ret;
690 }
691
693 [[nodiscard]] Node *lca(const Node *u, const Node *v) const
694 {
695 return node_of(lca_id(id_of(u), id_of(v)));
696 }
697
699 [[nodiscard]] size_t distance_id(const size_t u, const size_t v) const
700 {
701 const size_t a = lca_id(u, v);
702 return topology_.depth()(u) + topology_.depth()(v) - 2 * topology_.depth()(a);
703 }
704
706 [[nodiscard]] size_t distance(const Node *u, const Node *v) const
707 {
708 return distance_id(id_of(u), id_of(v));
709 }
710};
711
732template <AlephGraph GT, ArcFilter<GT> SA = Dft_Show_Arc<GT>>
734{
735public:
736 using Node = typename GT::Node;
737
738private:
740 static constexpr size_t NONE = Topology::NONE;
743
747
748 void ensure_not_empty(const char *where) const
749 {
750 ah_domain_error_if(is_empty()) << where << ": tree is empty";
751 }
752
755 {
756 if (is_empty())
757 return;
758
760 for (size_t i = 0; i < topology_.euler_size(); ++i)
761 {
762 const size_t node = topology_.euler()(i);
763 euler_depth_(i) = Depth_Node{topology_.depth()(node), node};
764 }
765
767 }
768
769public:
776 Gen_Euler_RMQ_LCA(const GT &g, Node *root, SA sa = SA())
777 : topology_(g, root, std::move(sa)), rmq_(1, Depth_Node(), Depth_Node_Min_Op())
778 {
779 build_rmq();
780 }
781
783 Gen_Euler_RMQ_LCA(const GT &g, SA sa = SA())
784 : topology_(g, nullptr, std::move(sa)), rmq_(1, Depth_Node(), Depth_Node_Min_Op())
785 {
786 build_rmq();
787 }
788
791 {
792 return topology_.size();
793 }
794
797 {
798 return topology_.is_empty();
799 }
800
803 {
804 return topology_.root();
805 }
806
809 {
810 return topology_.root_id();
811 }
812
814 [[nodiscard]] Node *node_of(const size_t id) const
815 {
816 return topology_.node_of(id);
817 }
818
820 [[nodiscard]] size_t id_of(const Node *node) const
821 {
822 return topology_.id_of(node);
823 }
824
826 [[nodiscard]] size_t depth_of_id(const size_t id) const
827 {
828 topology_.validate_id(id, "Gen_Euler_RMQ_LCA::depth_of_id");
829 return topology_.depth()(id);
830 }
831
833 [[nodiscard]] size_t depth_of(const Node *node) const
834 {
835 return depth_of_id(id_of(node));
836 }
837
839 [[nodiscard]] size_t parent_id(const size_t id) const
840 {
841 topology_.validate_id(id, "Gen_Euler_RMQ_LCA::parent_id");
842 return topology_.parent()(id);
843 }
844
846 [[nodiscard]] Node *parent_of(const Node *node) const
847 {
848 const size_t pid = parent_id(id_of(node));
849 return pid == NONE ? nullptr : node_of(pid);
850 }
851
853 [[nodiscard]] bool is_ancestor_id(const size_t u, const size_t v) const
854 {
855 return topology_.is_ancestor(u, v);
856 }
857
859 [[nodiscard]] bool is_ancestor(const Node *u, const Node *v) const
860 {
861 return is_ancestor_id(id_of(u), id_of(v));
862 }
863
865 [[nodiscard]] size_t lca_id(const size_t u, const size_t v) const
866 {
867 ensure_not_empty("Gen_Euler_RMQ_LCA::lca_id");
868 topology_.validate_id(u, "Gen_Euler_RMQ_LCA::lca_id");
869 topology_.validate_id(v, "Gen_Euler_RMQ_LCA::lca_id");
870
871 size_t l = topology_.first()(u);
872 size_t r = topology_.first()(v);
873 if (l > r)
874 std::swap(l, r);
875
876 return rmq_.query(l, r).node;
877 }
878
880 [[nodiscard]] Node *lca(const Node *u, const Node *v) const
881 {
882 return node_of(lca_id(id_of(u), id_of(v)));
883 }
884
886 [[nodiscard]] size_t distance_id(const size_t u, const size_t v) const
887 {
888 const size_t a = lca_id(u, v);
889 return topology_.depth()(u) + topology_.depth()(v) - 2 * topology_.depth()(a);
890 }
891
893 [[nodiscard]] size_t distance(const Node *u, const Node *v) const
894 {
895 return distance_id(id_of(u), id_of(v));
896 }
897
900 {
901 return topology_.euler();
902 }
903
906 {
907 return topology_.euler_size();
908 }
909};
910
912template <class GT, class SA = Dft_Show_Arc<GT>>
914
916template <class GT, class SA = Dft_Show_Arc<GT>>
918} // namespace Aleph
919
920#endif // LCA_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).
LCA via binary lifting on a rooted tree.
Definition LCA.H:467
size_t depth_of(const Node *node) const
Distance from root to node.
Definition LCA.H:606
size_t depth_of_id(const size_t id) const
Distance from root to node by ID.
Definition LCA.H:599
typename GT::Node Node
Definition LCA.H:469
Gen_Binary_Lifting_LCA(const GT &g, Node *root, SA sa=SA())
Construct from graph + explicit root.
Definition LCA.H:541
bool is_empty() const noexcept
Returns true if the tree has no nodes.
Definition LCA.H:563
Node * node_of(const size_t id) const
Map an internal ID [0, n-1] back to a Node pointer.
Definition LCA.H:587
size_t parent_id(const size_t id) const
Parent ID of node id, or NONE if root.
Definition LCA.H:612
size_t n() const noexcept
Definition LCA.H:479
size_t num_levels() const noexcept
Returns the number of levels in the jump table ( ).
Definition LCA.H:581
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).
Definition LCA.H:699
bool is_ancestor(const Node *u, const Node *v) const
Returns true if node u is an ancestor of v (or u == v).
Definition LCA.H:632
Node * kth_ancestor(const Node *node, const size_t k) const
k-th ancestor by node pointer in O(log n).
Definition LCA.H:655
Gen_Binary_Lifting_LCA(const GT &g, SA sa=SA())
Construct using the first graph node as root.
Definition LCA.H:551
size_t kth_ancestor_id(const size_t id, const size_t k) const
k-th ancestor by id in O(log n).
Definition LCA.H:643
size_t & up_at(const size_t k, const size_t v) noexcept
Definition LCA.H:484
size_t up_at(const size_t k, const size_t v) const noexcept
Definition LCA.H:489
Array< size_t > up_
Definition LCA.H:477
size_t id_of(const Node *node) const
Map a Node pointer to its internal ID [0, n-1].
Definition LCA.H:593
Node * root() const noexcept
Returns the root node of the tree.
Definition LCA.H:569
size_t lift(size_t v, size_t delta) const
Definition LCA.H:523
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).
Definition LCA.H:626
size_t distance(const Node *u, const Node *v) const
Number of edges on the path between two nodes in O(log n).
Definition LCA.H:706
size_t size() const noexcept
Total number of nodes in the tree.
Definition LCA.H:557
static constexpr size_t NONE
Definition LCA.H:473
size_t root_id() const noexcept
Returns the internal ID of the root node.
Definition LCA.H:575
size_t lca_id(size_t u, size_t v) const
LCA query by node ids in O(log n).
Definition LCA.H:662
Node * parent_of(const Node *node) const
Parent of node, or nullptr if root.
Definition LCA.H:619
Node * lca(const Node *u, const Node *v) const
LCA query by node pointers in O(log n).
Definition LCA.H:693
void ensure_not_empty(const char *where) const
Definition LCA.H:494
LCA via Euler tour + RMQ on depth in a rooted tree.
Definition LCA.H:734
Node * parent_of(const Node *node) const
Parent of node, or nullptr if root.
Definition LCA.H:846
static constexpr size_t NONE
Definition LCA.H:740
Node * node_of(const size_t id) const
Map an internal ID [0, n-1] back to a Node pointer.
Definition LCA.H:814
bool is_empty() const noexcept
Returns true if the tree has no nodes.
Definition LCA.H:796
lca_detail::Depth_Node_Min_Op Depth_Node_Min_Op
Definition LCA.H:742
Gen_Euler_RMQ_LCA(const GT &g, SA sa=SA())
Construct using the first graph node as root.
Definition LCA.H:783
typename GT::Node Node
Definition LCA.H:736
bool is_ancestor(const Node *u, const Node *v) const
Returns true if node u is an ancestor of v (or u == v).
Definition LCA.H:859
size_t id_of(const Node *node) const
Map a Node pointer to its internal ID [0, n-1].
Definition LCA.H:820
size_t depth_of_id(const size_t id) const
Distance from root to node by ID.
Definition LCA.H:826
size_t lca_id(const size_t u, const size_t v) const
LCA query by node ids in O(1).
Definition LCA.H:865
void ensure_not_empty(const char *where) const
Definition LCA.H:748
size_t size() const noexcept
Total number of nodes in the tree.
Definition LCA.H:790
Node * root() const noexcept
Returns the root node of the tree.
Definition LCA.H:802
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).
Definition LCA.H:886
Gen_Euler_RMQ_LCA(const GT &g, Node *root, SA sa=SA())
Construct from graph + explicit root.
Definition LCA.H:776
size_t root_id() const noexcept
Returns the internal ID of the root node.
Definition LCA.H:808
size_t depth_of(const Node *node) const
Distance from root to node.
Definition LCA.H:833
size_t parent_id(const size_t id) const
Parent ID of node id, or NONE if root.
Definition LCA.H:839
Node * lca(const Node *u, const Node *v) const
LCA query by node pointers in O(1).
Definition LCA.H:880
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).
Definition LCA.H:853
size_t euler_tour_size() const noexcept
Euler tour size ( for empty tree, else ).
Definition LCA.H:905
const Array< size_t > & euler_tour() const noexcept
Euler tour sequence of node ids ( entries).
Definition LCA.H:899
size_t distance(const Node *u, const Node *v) const
Number of edges on the path between two nodes in O(1).
Definition LCA.H:893
Gen_Sparse_Table< Depth_Node, Depth_Node_Min_Op > rmq_
Definition LCA.H:746
Array< Depth_Node > euler_depth_
Definition LCA.H:745
Sparse Table over an arbitrary associative and idempotent binary operation.
Filtered iterator on the nodes of a graph.
Definition tpl_graph.H:1207
Rooted_Tree_Data(const GT &g, Node *root, SA sa=SA())
Definition LCA.H:339
size_t root_id() const noexcept
Definition LCA.H:359
const Array< size_t > & depth() const noexcept
Definition LCA.H:372
Array< Array< size_t > > adjacency_
Definition LCA.H:147
MapOLhash< Node *, size_t > node_to_id_
Definition LCA.H:145
size_t size() const noexcept
Definition LCA.H:347
const Array< Node * > & id_to_node() const noexcept
Definition LCA.H:364
size_t euler_size() const noexcept
Definition LCA.H:392
Array< Node * > id_to_node_
Definition LCA.H:144
const Array< size_t > & euler() const noexcept
Definition LCA.H:388
static constexpr size_t NONE
Definition LCA.H:132
static Pair_Key normalize_pair(size_t u, size_t v) noexcept
Definition LCA.H:156
void check_id(const size_t id, const char *where) const
Definition LCA.H:332
Node * root() const noexcept
Definition LCA.H:355
bool is_ancestor(const size_t u, const size_t v) const
Definition LCA.H:418
const Array< size_t > & first() const noexcept
Definition LCA.H:384
const Array< size_t > & tout() const noexcept
Definition LCA.H:380
const Array< size_t > & tin() const noexcept
Definition LCA.H:376
Node * node_of(const size_t id) const
Definition LCA.H:407
const Array< size_t > & parent() const noexcept
Definition LCA.H:368
void validate_id(const size_t id, const char *where) const
Definition LCA.H:413
size_t id_of(const Node *node) const
Definition LCA.H:397
std::pair< size_t, size_t > Pair_Key
Definition LCA.H:135
bool is_empty() const noexcept
Definition LCA.H:351
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
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.
STL namespace.
Filtered iterator on all the arcs of a graph.
Definition tpl_graph.H:1165
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
Definition LCA.H:434
static int * k
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.
Sparse Table for static range queries in O(1).
DynList< int > l