Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Tarjan.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
32
92# ifndef TARJAN_H
93# define TARJAN_H
94
95# include <tpl_dynListStack.H>
96# include <tpl_dynSetTree.H>
97# include <htlist.H>
98# include <tpl_graph_utils.H>
99# include <tpl_find_path.H>
100# include <ah-errors.H>
101
102namespace Aleph
103{
167 template <class GT,
168 template <typename, class> class Itor = Out_Iterator,
169 class SA = Dft_Show_Arc<GT>>
171 {
173
174 GT *g_ptr = nullptr;
175
177
178 long df_count = 0;
179 mutable size_t n = 0; // number of nodes in the graph
180
181 Path<GT> *path_ptr = nullptr;
182
183 public:
186
188
191
193
200 : sa(std::move(__sa))
201 { /* empty */
202 }
203
204 private:
210 {
211 void operator ()(const GT & g, typename GT::Node *p) const noexcept
212 {
213 g.reset_bits(p);
214 g.reset_counter(p); // initialize df
215 low<GT>(p) = -1; // initialize low
216 }
217 };
218
223 bool is_node_in_stack(typename GT::Node *p) const noexcept
224 {
225 assert(p != nullptr);
226 return IS_NODE_VISITED(p, Aleph::Min);
227 }
228
237 {
239
240 stack.push(p);
241 NODE_BITS(p).set_bit(Aleph::Min, true);
242 NODE_BITS(p).set_bit(Aleph::Depth_First, true);
243 df<GT>(p) = low<GT>(p) = df_count++;
244 }
245
250 {
251 auto ret = stack.pop();
252 NODE_BITS(ret).set_bit(Aleph::Min, false);
253
254 return ret;
255 }
256
266 {
268
269 // depth-first traverse all nodes connected to v
270 for (Itor<GT, SA> it(v, sa); it.has_curr(); it.next_ne())
271 if (auto w = g_ptr->get_tgt_node(it.get_curr()); not IS_NODE_VISITED(w, Aleph::Depth_First))
272 {
274 low<GT>(v) = std::min(low<GT>(v), low<GT>(w));
275 }
276 else if (is_node_in_stack(w))
277 // if on stack ==> v was visited before w
278 low<GT>(v) = std::min(low<GT>(v), df<GT>(w));
279
280 if (low<GT>(v) == df<GT>(v)) // first visited node of the block?
281 { // yes ==> pop block nodes from stack
282 const auto & blk_idx = blk_list.size();
283 GT & blk = blk_list.append(GT());
284
285 while (true) // remove block from stack until v is removed
286 {
287 auto p = pop_from_stack();
288 auto q = blk.insert_node(p->get_info());
289 *q = *p; // copy node content
290 NODE_COOKIE(p) = NODE_COOKIE(q) = nullptr;
291 GT::map_nodes(p, q);
293 if (p == v)
294 break;
295 }
296 }
297 }
298
307 void scc_by_lists(typename GT::Node *v,
309 {
311
312 // depth traversal all nodes connected to v
313 for (Itor<GT, SA> it(v, sa); it.has_curr(); it.next_ne())
314 if (auto w = g_ptr->get_tgt_node(it.get_curr()); not IS_NODE_VISITED(w, Aleph::Depth_First))
315 {
317 low<GT>(v) = std::min(low<GT>(v), low<GT>(w));
318 }
319 else if (is_node_in_stack(w))
320 // if on stack ==> v was visited before w
321 low<GT>(v) = std::min(low<GT>(v), df<GT>(w));
322
323 if (low<GT>(v) == df<GT>(v)) // first visited node of the block?
324 { // yes pop out block nodes that are on stack
326 while (true) // remove block from stack until reaching v
327 {
328 auto p = pop_from_stack();
329 l.append(p);
330 if (p == v)
331 break;
332 }
333 }
334 }
335
345 {
347
348 // depth traverse all nodes connected to v
349 for (Itor<GT, SA> it(v, sa); it.has_curr(); it.next_ne())
350 if (auto w = g_ptr->get_tgt_node(it.get_curr()); not IS_NODE_VISITED(w, Aleph::Depth_First))
351 {
353 low<GT>(v) = std::min(low<GT>(v), low<GT>(w));
354 }
355 else if (is_node_in_stack(w))
356 // if on stack ==> v was visited before w
357 low<GT>(v) = std::min(low<GT>(v), df<GT>(w));
358
359 if (low<GT>(v) == df<GT>(v)) // first visited node of the block?
360 { // yes, pop out block nodes that are on the stack
361 size_t count = 0;
362 while (true) // remove block from the stack until reaching v
363 {
364 auto p = pop_from_stack();
365 ++count;
366
367 if (p == v)
368 break;
369 }
371 }
372 }
373
385 void init_tarjan(const GT & g)
386 {
387 Operate_On_Nodes<GT, Init_Tarjan_Node>()(g); // initialize bits, df and low
388 df_count = 0; // visitor counter
389 stack.empty();
390 n = g.get_num_nodes();
391
392 g_ptr = &const_cast<GT &>(g);
393 }
394
403 bool has_cycle(typename GT::Node *v)
404 {
406
407 // depth traverse all nodes connected to v
408 for (Itor<GT, SA> it(v, sa); it.has_curr(); it.next_ne())
409 {
410 auto w = g_ptr->get_tgt_node(it.get_curr());
411
412 // Check for self-loop (a cycle of length 1)
413 if (w == v)
414 return true;
415
417 {
418 if (has_cycle(w))
419 return true;
420
421 low<GT>(v) = std::min(low<GT>(v), low<GT>(w));
422 }
423 else if (is_node_in_stack(w))
424 // if on stack ==> v was visited before w
425 low<GT>(v) = std::min(low<GT>(v), df<GT>(w));
426 }
427
428 if (low<GT>(v) == df<GT>(v)) // first visited node of block?
429 { // yes, check if component has two or more nodes
430 size_t count = 0;
431 while (true)
432 {
433 ++count;
434 if (pop_from_stack() == v)
435 break;
436 }
437
438 return count >= 2; // if count >= 2 ==> there is a cycle
439 }
440
441 return false; // everything was covered without finding a cycle
442 }
443
452 void
453 build_path(const GT & block,
455 {
456 // Search for a cycle in the block
457 auto a = block.get_first_arc();
458 auto start = block.get_tgt_node(a);
459 auto end = block.get_src_node(a);
460 assert(start != end);
461
462 auto aux_path = Directed_Find_Path<GT, Itor, SA>(block, sa).dfs(start, end);
463 assert(not aux_path.is_empty()); // since it's connected it must be found
464
465 // aux_path is about the mapped block. We need to translate it back
466 // to the original graph using the mapping table.
467 path_ptr->empty();
468 for (typename Path<GT>::Iterator i(aux_path); i.has_curr(); i.next_ne())
469 path_ptr->append_directed(table.find(i.get_current_node_ne()));
470
471 path_ptr->append_directed(path_ptr->get_first_node());
472 }
473
481 bool build_cycle(typename GT::Node *v)
482 {
484
485 // depth traverse all nodes connected to v
486 for (Itor<GT, SA> it(v, sa); it.has_curr(); it.next_ne())
487 {
488 auto w = g_ptr->get_tgt_node(it.get_curr());
489
490 // Check for self-loop (a cycle of length 1)
491 if (w == v)
492 {
493 // Build a simple self-loop path: v -> v
494 path_ptr->empty();
495 path_ptr->init(v);
496 path_ptr->append_directed(v);
497 return true;
498 }
499
501 {
502 if (build_cycle(w))
503 return true;
504
505 low<GT>(v) = std::min(low<GT>(v), low<GT>(w));
506 }
507 else if (is_node_in_stack(w))
508 // if on stack ==> v was visited before w
509 low<GT>(v) = std::min(low<GT>(v), df<GT>(w));
510 }
511
512 if (low<GT>(v) == df<GT>(v)) //first visited node of the block?
513 {
514 GT blk; // auxiliary graph
515
516 //g node mapping to blk (cookies are busy)
518
519 // pop nodes from stack and insert them into auxiliary block
520 while (true) // pop the component and insert into blk
521 {
522 auto p = pop_from_stack();
523 auto q = blk.insert_node();
524 *q = *p; // copy node content
525 table.insert(q, p);
526 table.insert(p, q);
527 if (p == v)
528 break;
529 }
530
531 if (blk.get_num_nodes() == 1)
532 return false; // single node without self-loop ==> no cycle
533
534 // finish constructing the block with the arcs
535 for (typename GT::Node_Iterator j(blk); j.has_curr(); j.next_ne())
536 {
537 auto bsrc = j.get_curr();
538 auto gsrc = table.find(bsrc);
539
540 // traverse the arcs of gsrc
541 for (Itor<GT, SA> k(gsrc, sa); k.has_curr(); k.next_ne())
542 {
543 auto ga = k.get_curr();
544 auto gtgt = g_ptr->get_tgt_node(ga);
545 auto ptr = table.search(gtgt);
546 if (ptr == nullptr) // arc of the block?
547 continue;
548
549 auto ta = blk.insert_arc(bsrc, ptr->second);
550 *ta = *ga; // copy arc content
551 }
552 }
553
554 build_path(blk, table);
555
556 return true;
557 }
558
559 assert(path_ptr->is_empty());
560
561 return false;
562 }
563
572 bool is_connected(typename GT::Node *v)
573 {
575
576 // depth-first traverse all nodes connected to v
577 for (Itor<GT, SA> it(v, sa); it.has_curr(); it.next_ne())
578 {
579 if (auto w = g_ptr->get_tgt_node(it.get_curr()); not IS_NODE_VISITED(w, Aleph::Depth_First))
580 {
581 if (not is_connected(w))
582 return false;
583
584 low<GT>(v) = std::min(low<GT>(v), low<GT>(w));
585 }
586 else if (is_node_in_stack(w))
587 low<GT>(v) = std::min(low<GT>(v), df<GT>(w));
588 }
589
590 if (low<GT>(v) == df<GT>(v)) // first visited node of the block?
591 { // pop nodes from stack until v is found
592 while (pop_from_stack() != v);
593
594 return stack.is_empty();
595 }
596
597 return true;
598 }
599
600 public:
628 {
629 init_tarjan(g);
630
631 for (typename GT::Node_Iterator it(g); df_count < n; it.next_ne())
632 if (auto v = it.get_curr(); not IS_NODE_VISITED(v, Aleph::Depth_First))
634
636
637 // traverse each partial subgraph and add its arcs
638 for (typename DynList<GT>::Iterator i(blk_list); i.has_curr(); i.next_ne())
639 { // traverse all nodes of the block
640 GT & blk = i.get_curr();
641 for (typename GT::Node_Iterator j(blk); j.has_curr(); j.next_ne())
642 {
643 auto bsrc = j.get_curr();
644 auto gsrc = mapped_node<GT>(bsrc);
645
646 // traverse arcs of gsrc
647 for (Itor<GT, SA> k(gsrc, sa); k.has_curr(); k.next_ne())
648 {
649 auto ga = k.get_curr();
650 auto gtgt = g_ptr->get_tgt_node(ga);
652 { // inter-block arc ==> add it to arc_list
653 arc_list.append(ga);
654 continue;
655 }
656
657 // insert and map the arc in the sub-block
658 auto btgt = mapped_node<GT>(gtgt);
659 auto ba = blk.insert_arc(bsrc, btgt);
660 *ba = *ga; // copy arc content
662 }
663 }
664 }
665 }
666
698 void connected_components(const GT & g,
700 {
701 init_tarjan(g);
702 for (typename GT::Node_Iterator it(g); df_count < n; it.next_ne())
703 if (auto v = it.get_curr(); not IS_NODE_VISITED(v, Aleph::Depth_First))
704 scc_by_lists(v, blks);
705 }
706
713
725 {
728 return sizes.size();
729 }
730
752 {
753 init_tarjan(g);
754 for (typename GT::Node_Iterator it(g); df_count < n; it.next_ne())
755 if (auto v = it.get_curr(); not IS_NODE_VISITED(v, Aleph::Depth_First))
756 scc_by_len(v, blks);
757 }
758
768 void operator ()(const GT & g,
771 {
772 connected_components(g, blk_list, arc_list);
773 }
774
787
792
802 void operator ()(const GT & g,
805 {
809
810 for (typename DynList<GT>::Iterator it(blist); it.has_curr(); it.next_ne())
811 {
812 GT & curr = it.get_curr();
813 GT & block = blk_list.append(GT());
814 curr.swap(block);
815 }
816
818 it.has_curr(); it.next_ne())
819 arc_list.append(it.get_curr());
820 }
821
830 void operator ()(const GT & g,
832 {
835
836 for (typename DynList<DynList<typename GT::Node *>>::Iterator it(b);
837 it.has_curr(); it.next_ne())
838 {
840
841 auto & blk = it.get_curr();
842 while (not blk.is_empty())
844 }
845 }
846
858 [[nodiscard]] bool has_cycle(const GT & g)
859 {
860 init_tarjan(g);
861 for (typename GT::Node_Iterator it(g); df_count < n; it.next_ne())
862 if (auto v = it.get_curr(); not IS_NODE_VISITED(v, Aleph::Depth_First))
863 if (has_cycle(v))
864 return true;
865
866 return false;
867 }
868
879 [[nodiscard]] bool is_dag(const GT & g)
880 {
881 return not has_cycle(g);
882 }
883
897 bool compute_cycle(const GT & g, Path<GT> & path)
898 {
899 init_tarjan(g);
900 path_ptr = &path;
902
903 for (typename GT::Node_Iterator it(g); df_count < n; it.next_ne())
904 if (auto v = it.get_curr(); not IS_NODE_VISITED(v, Aleph::Depth_First)) // p visited?
905 if (build_cycle(v))
906 return true;
907
908 path.empty();
909 return false;
910 }
911
926 [[nodiscard]] bool compute_cycle(const GT & g, typename GT::Node *src, Path<GT> & path)
927 {
928 ah_domain_error_if(src == nullptr)
929 << "compute_cycle: source node cannot be null";
930
931 init_tarjan(g);
932 path_ptr = &path;
934 return build_cycle(src);
935 }
936
948 [[nodiscard]] bool test_connectivity(const GT & g)
949 {
950 init_tarjan(g);
951
952 // In a strongly connected graph, a single DFS from any node should reach
953 // all nodes. If we have to start from a second unvisited node, it means
954 // the graph has multiple disconnected components.
955 bool started = false;
956 for (typename GT::Node_Iterator it(g); df_count < n; it.next_ne())
957 if (auto v = it.get_curr(); not IS_NODE_VISITED(v, Aleph::Depth_First))
958 {
959 if (started) // Second DFS root → not strongly connected
960 return false;
961 started = true;
962 if (not is_connected(v))
963 return false;
964 }
965
967
968 return true;
969 }
970
973
977 SA &get_filter() noexcept { return sa; }
978
982 const SA &get_filter() const noexcept { return sa; }
983
987 [[nodiscard]] bool has_computation() const noexcept { return g_ptr != nullptr; }
988
993
995 };
996
997
1017 template <class GT,
1018 template <typename, class> class Itor = Out_Iterator,
1019 class SA = Dft_Show_Arc<GT>>
1021 {
1023
1024 public:
1031 : sa(std::move(__sa))
1032 { /* empty */
1033 }
1034
1043 [[nodiscard]] bool operator ()(const GT & g, Path<GT> & path) const
1044 {
1046
1047 return tarjan.compute_cycle(g, path);
1048 }
1049
1056 [[nodiscard]] Path<GT> operator ()(const GT & g) const
1057 {
1058 Path<GT> ret(g);
1060 return ret;
1061 }
1062
1071 [[nodiscard]] Path<GT> operator ()(const GT & g, typename GT::Node *src) const
1072 {
1073 Path<GT> ret(g);
1075 return ret;
1076 }
1077 };
1078} // end namespace Aleph
1079
1080# endif // TARJAN_H
Exception handling system with formatted messages for Aleph-w.
#define ah_domain_error_if(C)
Throws std::domain_error if condition holds.
Definition ah-errors.H:522
long double w
Definition btreepic.C:153
Determines if a digraph contains a cycle and constructs it.
Definition Tarjan.H:1021
bool operator()(const GT &g, Path< GT > &path) const
Invokes the computation of a cycle in a digraph.
Definition Tarjan.H:1043
Compute_Cycle_In_Digraph(SA __sa=SA())
Constructs a cycle computation instance with an arc filter.
Definition Tarjan.H:1030
Dynamic doubly linked list with O(1) size and bidirectional access.
T & append(const T &item)
Append a copied item at the end of the list.
Dynamic stack of elements of generic type T based on a singly linked list.
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.
void empty() noexcept
Remove all elements from the stack.
Iterator on the items of list.
Definition htlist.H:1714
Dynamic singly linked list with functional programming support.
Definition htlist.H:1423
T & append(const T &item)
Append a new item by copy.
Definition htlist.H:1562
Dynamic map implemented with an AVL tree.
Pair * search(const Key &key) const noexcept
Collect all keys.
Pair * insert(const Key &key, const Data &data)
Insert a key-value pair.
Data & find(const Key &key)
Find the value associated with key.
bool has_curr() const noexcept
Return true if iterator has current item.
Definition htlist.H:1150
constexpr bool is_empty() const noexcept
Return true if list is empty.
Definition htlist.H:523
size_t size() const noexcept
Count the number of elements of the list.
Definition htlist.H:1319
Arc * get_first_arc(Node *node) const
Return any arc adjacent to a node.
Definition tpl_graph.H:595
void swap(List_Graph &g) noexcept
Swap in constant time this with g
Definition tpl_graph.H:983
Filtered iterator for outcoming arcs of a node.
Definition tpl_graph.H:1750
Iterator on nodes and arcs of a path.
Definition tpl_graph.H:3201
Path on a graph.
Definition tpl_graph.H:2669
void empty()
Clean the path: all the nodes and arc are removed.
Definition tpl_graph.H:2819
void set_graph(const GT &__g, Node *start_node=nullptr)
Set the graph of the path.
Definition tpl_graph.H:2797
Computes strongly connected components (SCCs) in a directed graph using Tarjan's algorithm.
Definition Tarjan.H:171
void init_tarjan(const GT &g)
Initialize internal state for a Tarjan traversal.
Definition Tarjan.H:385
bool has_computation() const noexcept
Check if a computation has been performed.
Definition Tarjan.H:987
SA & get_filter() noexcept
Returns the arc filter used by this instance.
Definition Tarjan.H:977
DynList< DynList< typename GT::Node * > > connected_components(const GT &g)
Definition Tarjan.H:707
Tarjan_Connected_Components(const Tarjan_Connected_Components &)=delete
Tarjan instances should not be copied (they hold internal traversal state)
void init_node_and_push_in_stack(typename GT::Node *p)
Initialize a node and push it onto the traversal stack.
Definition Tarjan.H:236
bool is_node_in_stack(typename GT::Node *p) const noexcept
Check if a node is currently on the traversal stack.
Definition Tarjan.H:223
bool build_cycle(typename GT::Node *v)
Recursive DFS to find and construct a cycle starting from v.
Definition Tarjan.H:481
Tarjan_Connected_Components & operator=(const Tarjan_Connected_Components &)=delete
void connected_components(const GT &g, DynList< DynList< typename GT::Node * > > &blks)
Computes the strongly connected components of a digraph.
Definition Tarjan.H:698
bool test_connectivity(const GT &g)
Tests whether the digraph is strongly connected.
Definition Tarjan.H:948
bool has_cycle(typename GT::Node *v)
Recursive DFS to detect if a cycle exists starting from v.
Definition Tarjan.H:403
void connected_components(const GT &g, DynList< GT > &blk_list, DynList< typename GT::Arc * > &arc_list)
Computes the strongly connected components of a digraph.
Definition Tarjan.H:626
bool compute_cycle(const GT &g, typename GT::Node *src, Path< GT > &path)
Finds and constructs a cycle starting from a specific node, if one exists.
Definition Tarjan.H:926
void scc_by_lists(typename GT::Node *v, DynList< DynList< typename GT::Node * > > &blks)
Recursive DFS to find SCCs and collect nodes into lists.
Definition Tarjan.H:307
bool compute_cycle(const GT &g, Path< GT > &path)
Finds and constructs a cycle in the digraph, if one exists.
Definition Tarjan.H:897
void build_path(const GT &block, DynMapAvlTree< typename GT::Node *, typename GT::Node * > &table)
Build a cycle path from a strongly connected block.
Definition Tarjan.H:453
GT * get_graph() const noexcept
Get the graph of the last computation.
Definition Tarjan.H:992
const SA & get_filter() const noexcept
Returns the arc filter used by this instance (const version).
Definition Tarjan.H:982
bool has_cycle(const GT &g)
Determines whether the digraph contains at least one cycle.
Definition Tarjan.H:858
Tarjan_Connected_Components(Tarjan_Connected_Components &&)=default
Move is allowed.
bool is_dag(const GT &g)
Determines whether the directed graph is acyclic (a DAG).
Definition Tarjan.H:879
Tarjan_Connected_Components(SA __sa=SA()) noexcept
Constructs a Tarjan algorithm instance for computing strongly connected components.
Definition Tarjan.H:199
void scc_by_len(typename GT::Node *v, DynList< size_t > &sizes)
Recursive DFS to find SCCs and count their sizes.
Definition Tarjan.H:344
GT::Node * pop_from_stack()
Pop a node from the traversal stack.
Definition Tarjan.H:249
DynListStack< typename GT::Node * > stack
Definition Tarjan.H:176
void connected_components(const GT &g, DynList< size_t > &blks)
Computes the strongly connected components of a digraph.
Definition Tarjan.H:751
void operator()(const GT &g, DynList< GT > &blk_list, DynList< typename GT::Arc * > &arc_list)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition Tarjan.H:768
void scc_by_blocks(typename GT::Node *v, DynList< GT > &blk_list)
Recursive DFS to find SCCs and build mapped subgraphs.
Definition Tarjan.H:265
Tarjan_Connected_Components & operator=(Tarjan_Connected_Components &&)=default
bool is_connected(typename GT::Node *v)
Recursive DFS to test if the graph is strongly connected.
Definition Tarjan.H:572
size_t num_connected_components(const GT &g)
Returns the number of strongly connected components in the graph.
Definition Tarjan.H:724
Node * get_src_node(Arc *arc) const noexcept
Return the source node of arc (only for directed graphs)
Definition graph-dry.H:731
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
static void map_arcs(A1 *p, A2 *q) noexcept
Map the arcs through their cookies.
Definition graph-dry.H:1026
Node * get_tgt_node(Arc *arc) const noexcept
Return the target node of arc (only for directed graphs)
Definition graph-dry.H:737
static void map_nodes(N1 *p, N2 *q) noexcept
Map the nodes through their cookies.
Definition graph-dry.H:995
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
#define NODE_COUNTER(p)
Get the counter of a node.
#define IS_NODE_VISITED(p, bit)
Determine whether the control bit is set or not to one.
#define NODE_COOKIE(p)
Return the node cookie
#define NODE_BITS(p)
Get the control bits of a node.
@ Depth_First
Definition aleph-graph.H:73
Singly linked list implementations with head-tail access.
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Count elements equal to a value.
Definition ahAlgo.H:127
STL namespace.
Default filter for filtered iterators on arcs.
Definition tpl_graph.H:1000
Functor to initialize node metadata for Tarjan traversal.
Definition Tarjan.H:210
void operator()(const GT &g, typename GT::Node *p) const noexcept
Definition Tarjan.H:211
Dynamic stack implementation based on linked lists.
Dynamic set implementations based on balanced binary search trees.
Path finding algorithms in graphs.
Utility algorithms and operations for graphs.
DynList< int > l