Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
test_zero_one_bfs.cc
Go to the documentation of this file.
1
9# include <gtest/gtest.h>
10# include <Zero_One_BFS.H>
11# include <Dijkstra.H>
12# include <tpl_graph.H>
13# include <tpl_sgraph.H>
14# include <tpl_agraph.H>
15
16using namespace Aleph;
17
18// ============================================================================
19// Type aliases
20// ============================================================================
21
22// Undirected graph with integer weights
24using Node = GT::Node;
25using Arc = GT::Arc;
26
27// Directed graph with integer weights
30using DArc = DGT::Arc;
31
32// ============================================================================
33// TEST 1: Basic shortest path with mixed 0/1 weights
34// ============================================================================
36{
37 GT g;
38 auto n0 = g.insert_node(0);
39 auto n1 = g.insert_node(1);
40 auto n2 = g.insert_node(2);
41 auto n3 = g.insert_node(3);
42
43 g.insert_arc(n0, n1, 1);
44 g.insert_arc(n1, n2, 0);
45 g.insert_arc(n2, n3, 1);
46 g.insert_arc(n0, n3, 1); // direct but same cost
47
49 Path<GT> path(g);
50 int d = bfs(g, n0, n3, path);
51
52 // Direct path n0->n3 costs 1, path through n1,n2 costs 1+0+1=2
53 EXPECT_EQ(d, 1);
54 EXPECT_FALSE(path.is_empty());
55}
56
57// ============================================================================
58// TEST 2: All zero weights
59// ============================================================================
61{
62 GT g;
63 auto n0 = g.insert_node(0);
64 auto n1 = g.insert_node(1);
65 auto n2 = g.insert_node(2);
66 auto n3 = g.insert_node(3);
67
68 g.insert_arc(n0, n1, 0);
69 g.insert_arc(n1, n2, 0);
70 g.insert_arc(n2, n3, 0);
71
73 Path<GT> path(g);
74 int d = bfs(g, n0, n3, path);
75
76 EXPECT_EQ(d, 0);
77}
78
79// ============================================================================
80// TEST 3: All one weights
81// ============================================================================
83{
84 GT g;
85 auto n0 = g.insert_node(0);
86 auto n1 = g.insert_node(1);
87 auto n2 = g.insert_node(2);
88 auto n3 = g.insert_node(3);
89
90 g.insert_arc(n0, n1, 1);
91 g.insert_arc(n1, n2, 1);
92 g.insert_arc(n2, n3, 1);
93
95 Path<GT> path(g);
96 int d = bfs(g, n0, n3, path);
97
98 EXPECT_EQ(d, 3);
99}
100
101// ============================================================================
102// TEST 4: Path to self
103// ============================================================================
105{
106 GT g;
107 auto n0 = g.insert_node(0);
108 g.insert_arc(n0, n0, 1);
109
111 Path<GT> path(g);
112 int d = bfs(g, n0, n0, path);
113
114 // Start == end: trivially reachable, distance 0
115 EXPECT_EQ(d, 0);
116}
117
118// ============================================================================
119// TEST 5: No path exists (disconnected)
120// ============================================================================
122{
123 GT g;
124 auto n0 = g.insert_node(0);
125 auto n1 = g.insert_node(1);
126 auto n2 = g.insert_node(2);
127
128 g.insert_arc(n0, n1, 1);
129 // n2 is disconnected
130
132 Path<GT> path(g);
133 int d = bfs(g, n0, n2, path);
134
135 EXPECT_EQ(d, std::numeric_limits<int>::max());
136 EXPECT_TRUE(path.is_empty());
137}
138
139// ============================================================================
140// TEST 6: Single node graph
141// ============================================================================
143{
144 GT g;
145 auto n0 = g.insert_node(0);
146
148 Path<GT> path(g);
149 int d = bfs(g, n0, n0, path);
150
151 EXPECT_EQ(d, 0);
152}
153
154// ============================================================================
155// TEST 7: Linear chain
156// ============================================================================
158{
159 GT g;
160 auto n0 = g.insert_node(0);
161 auto n1 = g.insert_node(1);
162 auto n2 = g.insert_node(2);
163 auto n3 = g.insert_node(3);
164 auto n4 = g.insert_node(4);
165
166 g.insert_arc(n0, n1, 1);
167 g.insert_arc(n1, n2, 0);
168 g.insert_arc(n2, n3, 1);
169 g.insert_arc(n3, n4, 0);
170
172 Path<GT> path(g);
173 int d = bfs(g, n0, n4, path);
174
175 EXPECT_EQ(d, 2); // 1 + 0 + 1 + 0
176}
177
178// ============================================================================
179// TEST 8: 0-weight shortcut
180// ============================================================================
182{
183 GT g;
184 auto n0 = g.insert_node(0);
185 auto n1 = g.insert_node(1);
186 auto n2 = g.insert_node(2);
187 auto n3 = g.insert_node(3);
188
189 // Long path: n0->n1->n2->n3 costs 1+1+1=3
190 g.insert_arc(n0, n1, 1);
191 g.insert_arc(n1, n2, 1);
192 g.insert_arc(n2, n3, 1);
193
194 // Shortcut: n0->n3 via zero-cost edges
195 auto n4 = g.insert_node(4);
196 g.insert_arc(n0, n4, 0);
197 g.insert_arc(n4, n3, 0);
198
200 Path<GT> path(g);
201 int d = bfs(g, n0, n3, path);
202
203 EXPECT_EQ(d, 0); // Free path via n4
204}
205
206// ============================================================================
207// TEST 9: Null node validation
208// ============================================================================
210{
211 GT g;
212 auto n0 = g.insert_node(0);
213
215 Path<GT> path(g);
216
217 EXPECT_THROW(bfs(g, nullptr, n0, path), std::domain_error);
218 EXPECT_THROW(bfs(g, n0, nullptr, path), std::domain_error);
219}
220
221// ============================================================================
222// TEST 10: Empty graph validation
223// ============================================================================
225{
226 GT g;
227
229 Path<GT> path(g);
230
231 EXPECT_EQ(g.get_num_nodes(), 0u);
232
233 // According to API, search nodes must be non-null and belong to g.
234 // For empty graph, any node is invalid.
235 Node * n = nullptr;
236 EXPECT_THROW(bfs(g, n, n, path), std::domain_error);
237 EXPECT_TRUE(path.is_empty());
238}
239
240// ============================================================================
241// TEST 11: Invalid weight validation
242// ============================================================================
244{
245 GT g;
246 auto n0 = g.insert_node(0);
247 auto n1 = g.insert_node(1);
248
249 auto a01 = g.insert_arc(n0, n1, 2); // Invalid weight!
250
252 Path<GT> path(g);
253
254 EXPECT_THROW(bfs(g, n0, n1, path), std::domain_error);
255 EXPECT_EQ(NODE_COOKIE(n0), nullptr);
256 EXPECT_EQ(NODE_COOKIE(n1), nullptr);
260}
261
262// ============================================================================
263// TEST 12: Paint and then get_min_path
264// ============================================================================
266{
267 GT g;
268 auto n0 = g.insert_node(0);
269 auto n1 = g.insert_node(1);
270 auto n2 = g.insert_node(2);
271 auto n3 = g.insert_node(3);
272
273 g.insert_arc(n0, n1, 1);
274 g.insert_arc(n1, n2, 0);
275 g.insert_arc(n2, n3, 1);
276
278 bfs.paint_min_paths_tree(g, n0);
279
280 EXPECT_TRUE(bfs.is_painted());
281 EXPECT_EQ(bfs.get_start_node(), n0);
282
283 Path<GT> path(g);
284 int d = bfs.get_min_path(n3, path);
285 EXPECT_EQ(d, 2);
286 EXPECT_FALSE(path.is_empty());
287}
288
289// ============================================================================
290// TEST 13: Get distance after painting
291// ============================================================================
293{
294 GT g;
295 auto n0 = g.insert_node(0);
296 auto n1 = g.insert_node(1);
297 auto n2 = g.insert_node(2);
298 auto n3 = g.insert_node(3);
299
300 g.insert_arc(n0, n1, 1);
301 g.insert_arc(n1, n2, 0);
302 g.insert_arc(n2, n3, 1);
303
305 bfs.paint_min_paths_tree(g, n0);
306
307 EXPECT_EQ(bfs.get_distance(n0), 0);
308 EXPECT_EQ(bfs.get_distance(n1), 1);
309 EXPECT_EQ(bfs.get_distance(n2), 1);
310 EXPECT_EQ(bfs.get_distance(n3), 2);
311}
312
313// ============================================================================
314// TEST 14: Get distance before painting
315// ============================================================================
317{
318 GT g;
319 auto n0 = g.insert_node(0);
320
322 EXPECT_THROW(bfs.get_distance(n0), std::domain_error);
323}
324
325// ============================================================================
326// TEST 15: Path node-by-node verification
327// ============================================================================
329{
330 GT g;
331 auto n0 = g.insert_node(0);
332 auto n1 = g.insert_node(1);
333 auto n2 = g.insert_node(2);
334 auto n3 = g.insert_node(3);
335
336 g.insert_arc(n0, n1, 1);
337 g.insert_arc(n1, n2, 0);
338 g.insert_arc(n2, n3, 1);
339 g.insert_arc(n0, n3, 1); // direct path, same cost as via n1,n2
340
342 Path<GT> path(g);
343 int d = bfs(g, n0, n3, path);
344
345 EXPECT_EQ(d, 1);
346
347 // Collect path nodes
349 for (Path<GT>::Iterator it(path); it.has_curr(); it.next())
350 nodes.append(it.get_current_node()->get_info());
351
352 // Path should be n0 -> n3 (direct)
353 ASSERT_EQ(nodes.size(), 2u);
354 auto pit = nodes.get_it();
355 EXPECT_EQ(pit.get_curr(), 0); pit.next();
356 EXPECT_EQ(pit.get_curr(), 3);
357}
358
359// ============================================================================
360// TEST 16: Complete graph K4 with 0/1 weights
361// ============================================================================
363{
364 GT g;
365 auto n0 = g.insert_node(0);
366 auto n1 = g.insert_node(1);
367 auto n2 = g.insert_node(2);
368 auto n3 = g.insert_node(3);
369
370 g.insert_arc(n0, n1, 1);
371 g.insert_arc(n0, n2, 0);
372 g.insert_arc(n0, n3, 1);
373 g.insert_arc(n1, n2, 1);
374 g.insert_arc(n1, n3, 0);
375 g.insert_arc(n2, n3, 1);
376
378 Path<GT> path(g);
379 int d = bfs(g, n0, n3, path);
380
381 // Best: n0->n2(0)->n3(1)? No, n0->n1(1)->n3(0)=1, n0->n2(0)+n2->n3(1)=1
382 // or n0->n3(1)=1. All paths cost 1.
383 EXPECT_EQ(d, 1);
384}
385
386// ============================================================================
387// TEST 17: Graph with cycle
388// ============================================================================
390{
391 GT g;
392 auto n0 = g.insert_node(0);
393 auto n1 = g.insert_node(1);
394 auto n2 = g.insert_node(2);
395 auto n3 = g.insert_node(3);
396
397 g.insert_arc(n0, n1, 1);
398 g.insert_arc(n1, n2, 1);
399 g.insert_arc(n2, n0, 1); // cycle back
400 g.insert_arc(n2, n3, 0);
401
403 Path<GT> path(g);
404 int d = bfs(g, n0, n3, path);
405
406 // Undirected: n0->n2(via arc n2-n0, weight 1)->n3(weight 0) = 1
407 EXPECT_EQ(d, 1);
408}
409
410// ============================================================================
411// TEST 18: Directed graph basic
412// ============================================================================
414{
415 DGT g;
416 auto n0 = g.insert_node(0);
417 auto n1 = g.insert_node(1);
418 auto n2 = g.insert_node(2);
419
420 g.insert_arc(n0, n1, 1);
421 g.insert_arc(n1, n2, 0);
422
424 Path<DGT> path(g);
425 int d = bfs(g, n0, n2, path);
426
427 EXPECT_EQ(d, 1);
428}
429
430// ============================================================================
431// TEST 19: Directed graph no reverse path
432// ============================================================================
434{
435 DGT g;
436 auto n0 = g.insert_node(0);
437 auto n1 = g.insert_node(1);
438
439 g.insert_arc(n0, n1, 1); // only forward
440
442
444 int d1 = bfs(g, n0, n1, path_fwd);
445 EXPECT_EQ(d1, 1);
446
448 int d2 = bfs(g, n1, n0, path_bck);
449 EXPECT_EQ(d2, std::numeric_limits<int>::max());
450}
451
452// ============================================================================
453// TEST 20: Multiple successive computations
454// ============================================================================
456{
457 GT g;
458 auto n0 = g.insert_node(0);
459 auto n1 = g.insert_node(1);
460 auto n2 = g.insert_node(2);
461
462 g.insert_arc(n0, n1, 1);
463 g.insert_arc(n1, n2, 0);
464
466
467 Path<GT> p1(g);
468 int d1 = bfs(g, n0, n2, p1);
469 EXPECT_EQ(d1, 1);
470
471 Path<GT> p2(g);
472 int d2 = bfs(g, n2, n0, p2);
473 EXPECT_EQ(d2, 1); // Same in undirected
474}
475
476// ============================================================================
477// TEST 21: Large linear graph
478// ============================================================================
480{
481 GT g;
482 const int N = 200;
483
485 for (int i = 0; i < N; ++i)
486 nodes[i] = g.insert_node(i);
487
488 // Alternating 0 and 1 weights
489 for (int i = 0; i < N - 1; ++i)
490 g.insert_arc(nodes[i], nodes[i + 1], i % 2);
491
493 Path<GT> path(g);
494 int d = bfs(g, nodes[0], nodes[N - 1], path);
495
496 // Count of 1-weight edges: indices 1, 3, 5, ... (odd indices)
497 int expected = (N - 1) / 2;
499}
500
501// ============================================================================
502// TEST 22: Cross-validation with Dijkstra
503// ============================================================================
505{
506 GT g;
507 auto n0 = g.insert_node(0);
508 auto n1 = g.insert_node(1);
509 auto n2 = g.insert_node(2);
510 auto n3 = g.insert_node(3);
511 auto n4 = g.insert_node(4);
512 auto n5 = g.insert_node(5);
513
514 g.insert_arc(n0, n1, 0);
515 g.insert_arc(n0, n2, 1);
516 g.insert_arc(n1, n3, 1);
517 g.insert_arc(n2, n3, 0);
518 g.insert_arc(n3, n4, 1);
519 g.insert_arc(n1, n5, 0);
520 g.insert_arc(n5, n4, 0);
521
522 // 0-1 BFS
525 int bfs_d = bfs(g, n0, n4, bfs_path);
526
527 // Dijkstra (should give same result)
528 using IGT = GT; // same type
531 int dij_d = dij(g, n0, n4, dij_path);
532
534}
535
536// ============================================================================
537// TEST 23: Star graph with mixed weights
538// ============================================================================
540{
541 GT g;
542 auto center = g.insert_node(0);
543 auto n1 = g.insert_node(1);
544 auto n2 = g.insert_node(2);
545 auto n3 = g.insert_node(3);
546 auto n4 = g.insert_node(4);
547
548 g.insert_arc(center, n1, 0);
549 g.insert_arc(center, n2, 1);
550 g.insert_arc(center, n3, 0);
551 g.insert_arc(center, n4, 1);
552
554 bfs.paint_min_paths_tree(g, center);
555
556 EXPECT_EQ(bfs.get_distance(n1), 0);
557 EXPECT_EQ(bfs.get_distance(n2), 1);
558 EXPECT_EQ(bfs.get_distance(n3), 0);
559 EXPECT_EQ(bfs.get_distance(n4), 1);
560}
561
562// ============================================================================
563// TEST 24: Grid-like graph (illustrative example)
564// ============================================================================
565// === EXAMPLE: Grid navigation with free/paid passages ===
566// Imagine a 3x3 grid where some passages are free (weight 0)
567// and others cost 1 unit. Find shortest path from top-left to
568// bottom-right.
569//
570// (0,0) --0-- (0,1) --1-- (0,2)
571// | | |
572// 1 0 1
573// | | |
574// (1,0) --1-- (1,1) --0-- (1,2)
575// | | |
576// 0 1 0
577// | | |
578// (2,0) --0-- (2,1) --0-- (2,2)
579//
581{
582 GT g;
583
584 // Create 3x3 grid nodes (row * 3 + col as node info)
585 Node * grid[3][3];
586 for (int r = 0; r < 3; ++r)
587 for (int c = 0; c < 3; ++c)
588 grid[r][c] = g.insert_node(r * 3 + c);
589
590 // Horizontal edges
591 g.insert_arc(grid[0][0], grid[0][1], 0);
592 g.insert_arc(grid[0][1], grid[0][2], 1);
593 g.insert_arc(grid[1][0], grid[1][1], 1);
594 g.insert_arc(grid[1][1], grid[1][2], 0);
595 g.insert_arc(grid[2][0], grid[2][1], 0);
596 g.insert_arc(grid[2][1], grid[2][2], 0);
597
598 // Vertical edges
599 g.insert_arc(grid[0][0], grid[1][0], 1);
600 g.insert_arc(grid[0][1], grid[1][1], 0);
601 g.insert_arc(grid[0][2], grid[1][2], 1);
602 g.insert_arc(grid[1][0], grid[2][0], 0);
603 g.insert_arc(grid[1][1], grid[2][1], 1);
604 g.insert_arc(grid[1][2], grid[2][2], 0);
605
607 Path<GT> path(g);
608 int d = bfs(g, grid[0][0], grid[2][2], path);
609
610 // Best path: (0,0)->0->(0,1)->0->(1,1)->0->(1,2)->0->(2,2) = 0
611 EXPECT_EQ(d, 0);
612}
613
614// ============================================================================
615// TEST 25: Two-node graph weight 0
616// ============================================================================
618{
619 GT g;
620 auto n0 = g.insert_node(0);
621 auto n1 = g.insert_node(1);
622
623 g.insert_arc(n0, n1, 0);
624
626 Path<GT> path(g);
627 int d = bfs(g, n0, n1, path);
628
629 EXPECT_EQ(d, 0);
630}
631
632// ============================================================================
633// TEST 26: Two-node graph weight 1
634// ============================================================================
636{
637 GT g;
638 auto n0 = g.insert_node(0);
639 auto n1 = g.insert_node(1);
640
641 g.insert_arc(n0, n1, 1);
642
644 Path<GT> path(g);
645 int d = bfs(g, n0, n1, path);
646
647 EXPECT_EQ(d, 1);
648}
649
650// ============================================================================
651// TEST 27: Negative weight validation
652// ============================================================================
654{
655 GT g;
656 auto n0 = g.insert_node(0);
657 auto n1 = g.insert_node(1);
658
659 auto a01 = g.insert_arc(n0, n1, -1);
660
662 Path<GT> path(g);
663
664 EXPECT_THROW(bfs(g, n0, n1, path), std::domain_error);
665 EXPECT_EQ(NODE_COOKIE(n0), nullptr);
666 EXPECT_EQ(NODE_COOKIE(n1), nullptr);
670}
671
672// ============================================================================
673// TEST 28: State getters
674// ============================================================================
676{
677 GT g;
678 auto n0 = g.insert_node(0);
679 auto n1 = g.insert_node(1);
680 g.insert_arc(n0, n1, 1);
681
683
685 EXPECT_EQ(bfs.get_start_node(), nullptr);
686 EXPECT_EQ(bfs.get_graph(), nullptr);
687
688 bfs.paint_min_paths_tree(g, n0);
689
690 EXPECT_TRUE(bfs.is_painted());
691 EXPECT_EQ(bfs.get_start_node(), n0);
692 EXPECT_EQ(bfs.get_graph(), &g);
693}
694
695// ============================================================================
696// TEST 29: Disconnected graph painting
697// ============================================================================
699{
700 GT g;
701 auto n0 = g.insert_node(0);
702 auto n1 = g.insert_node(1);
703 auto n2 = g.insert_node(2);
704 auto n3 = g.insert_node(3);
705
706 g.insert_arc(n0, n1, 1);
707 g.insert_arc(n2, n3, 0);
708
710 bfs.paint_min_paths_tree(g, n0);
711
712 EXPECT_EQ(bfs.get_distance(n1), 1);
713 EXPECT_THROW(bfs.get_distance(n2), std::domain_error);
714}
715
716// ============================================================================
717// TEST 30: Large graph with many zero edges
718// ============================================================================
720{
721 GT g;
722 const int N = 100;
723
725 for (int i = 0; i < N; ++i)
726 nodes[i] = g.insert_node(i);
727
728 // Chain with all zero weights
729 for (int i = 0; i < N - 1; ++i)
730 g.insert_arc(nodes[i], nodes[i + 1], 0);
731
732 // Add a single 1-weight shortcut
733 g.insert_arc(nodes[0], nodes[N - 1], 1);
734
736 Path<GT> path(g);
737 int d = bfs(g, nodes[0], nodes[N - 1], path);
738
739 EXPECT_EQ(d, 0); // Zero-cost chain is better than weight-1 shortcut
740}
741
742// ============================================================================
743// TEST 31: Parallel edges must not leave stale spanning-tree arc marks
744// ============================================================================
746{
747 GT g;
748 auto start = g.insert_node(0);
749 auto mid = g.insert_node(1);
750 auto end = g.insert_node(2);
751
752 auto direct_one = g.insert_arc(start, end, 1);
753 auto start_mid_zero = g.insert_arc(start, mid, 0);
754 auto mid_end_one = g.insert_arc(mid, end, 1);
755 auto mid_end_zero = g.insert_arc(mid, end, 0); // Parallel arc, better cost
756
758 bfs.paint_min_paths_tree(g, start);
759
760 EXPECT_EQ(bfs.get_distance(end), 0);
763
768
769 size_t painted_arcs = 0;
770 for (GT::Arc_Iterator it(g); it.has_curr(); it.next())
771 if (IS_ARC_VISITED(it.get_curr(), Aleph::Spanning_Tree))
772 ++painted_arcs;
773
775}
776
777// ============================================================================
778// TEST 32: Destructor must restore graph state and release NODE_COOKIE storage
779// ============================================================================
Dijkstra's shortest path algorithm.
0-1 BFS shortest path algorithm.
WeightedDigraph::Node Node
WeightedDigraph::Arc Arc
static Array create(size_t n)
Create an array with n logical elements.
Definition tpl_array.H:194
Generic directed graph (digraph) wrapper template.
Definition graph-dry.H:3854
typename BaseGraph::Arc Arc
Definition graph-dry.H:3858
typename BaseGraph::Node Node
Definition graph-dry.H:3857
Spanning tree calculation of all shortest paths from a given node according to Dijkstra's algorithm.
Definition Dijkstra.H:101
Dynamic singly linked list with functional programming support.
Definition htlist.H:1155
T & append(const T &item)
Definition htlist.H:1271
virtual Node * insert_node(Node *node) noexcept
Insertion of a node already allocated.
Definition tpl_graph.H:524
Graph_Arc< int > Arc
The node class type.
Definition tpl_graph.H:433
Arc * insert_arc(Node *src_node, Node *tgt_node, void *a)
Definition tpl_graph.H:604
Iterator on nodes and arcs of a path.
Definition tpl_graph.H:3208
Path on a graph.
Definition tpl_graph.H:2669
bool is_empty() const noexcept
Return true if the path is empty.
Definition tpl_graph.H:2813
0-1 BFS algorithm for shortest paths in graphs with 0/1 weights.
bool is_painted() const noexcept
Check if a computation has been performed.
GT * get_graph() const noexcept
Get the graph of the last computation.
Distance_Type get_min_path(Node *end, Path< GT > &path)
Extracts a shortest path from a previously painted graph.
void paint_min_paths_tree(const GT &g, Node *start)
Paints the shortest paths tree on the graph from start.
Distance_Type get_distance(Node *node)
Gets the accumulated distance to a node after painting.
Node * get_start_node() const noexcept
Get the start node of the last computation.
constexpr size_t get_num_nodes() const noexcept
Return the total of nodes of graph.
Definition graph-dry.H:695
#define TEST(name)
#define N
Definition fib.C:294
DynArray< Graph::Node * > nodes
Definition graphpic.C:406
#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 IS_ARC_VISITED(p, bit)
Determine whether the bit field is or not set to one.
@ Spanning_Tree
Definition aleph-graph.H:79
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
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.
Arc of graph implemented with double-linked adjacency lists.
Definition tpl_graph.H:222
DGT::Arc DArc
DGT::Node DNode
gsl_rng * r
List_Graph< Graph_Node< int >, Graph_Arc< int > > GT
Array-based graph implementation.
Generic graph and digraph implementations.
Simple graph implementation with adjacency lists.