123using namespace Aleph;
156 return arc->get_info();
189 nodes.push_back(g.insert_node(
"Alpha"));
190 nodes.push_back(g.insert_node(
"Beta"));
191 nodes.push_back(g.insert_node(
"Gamma"));
192 nodes.push_back(g.insert_node(
"Delta"));
193 nodes.push_back(g.insert_node(
"Epsilon"));
194 nodes.push_back(g.insert_node(
"Zeta"));
195 nodes.push_back(g.insert_node(
"Eta"));
196 nodes.push_back(g.insert_node(
"Theta"));
264 cout <<
"\n┌─────────────────────────────────────────┐\n";
265 cout <<
"│ City Road Network │\n";
266 cout <<
"├─────────────────────────────────────────┤\n";
267 cout <<
"│ Cities: " <<
setw(3) << g.get_num_nodes()
269 cout <<
"│ Roads: " <<
setw(3) << g.get_num_arcs() / 2
270 <<
" (bidirectional) │\n";
271 cout <<
"└─────────────────────────────────────────┘\n\n";
273 cout <<
"Connections:\n";
274 for (
auto nit = g.get_node_it();
nit.has_curr();
nit.next())
276 auto* node =
nit.get_curr();
277 cout <<
" " <<
setw(8) << left << node->get_info() << right <<
" → ";
279 for (
auto ait = g.get_out_it(node);
ait.has_curr();
ait.next())
281 auto* arc =
ait.get_curr();
282 auto* tgt = g.get_tgt_node(arc);
283 if (!first)
cout <<
", ";
284 cout << tgt->get_info() <<
"(" << arc->get_info() <<
")";
296 if (path.
size() == 0)
298 cout <<
" (empty path)\n";
303 cout <<
"\n Route: ";
306 if (!first)
cout <<
" → ";
307 cout << node->get_info();
313 if (path.
size() <= 1)
316 cout <<
" Step-by-step:\n";
317 cout <<
" ┌──────────────────────────────────────────────────┐\n";
318 cout <<
" │ From Distance To Cumulative│\n";
319 cout <<
" ├──────────────────────────────────────────────────┤\n";
324 cout <<
" │ " <<
setw(8) << left << g.get_src_node(arc)->get_info()
325 <<
" ──" <<
setw(5) << right << arc->get_info() <<
" km──▶ "
326 <<
setw(8) << left << g.get_tgt_node(arc)->get_info()
329 cout <<
" └──────────────────────────────────────────────────┘\n";
336template <
typename Func>
339 auto start = chrono::high_resolution_clock::now();
341 auto end = chrono::high_resolution_clock::now();
342 return chrono::duration<double, milli>(end - start).count();
351 cout <<
"╔══════════════════════════════════════════════════════════════════╗\n";
352 cout <<
"║ Dijkstra's Shortest Path Algorithm - Example ║\n";
353 cout <<
"╚══════════════════════════════════════════════════════════════════╝\n";
359 cout <<
"\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
360 cout <<
"Part 1: Basic Usage - Finding Shortest Path\n";
361 cout <<
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
369 auto* source =
nodes[0];
372 cout <<
"\n▶ Finding shortest path from " << source->get_info()
373 <<
" to " <<
dest->get_info() <<
":\n";
380 double distance =
dijkstra.find_min_path(g, source,
dest, path);
382 cout <<
"\n Total distance: " << distance <<
" km\n";
383 cout <<
" Path length: " << path.
size() <<
" cities\n";
391 cout <<
"\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
392 cout <<
"Part 2: Computing Complete Shortest Paths Tree\n";
393 cout <<
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
395 cout <<
"\nWhen you need shortest paths to MULTIPLE destinations, compute\n";
396 cout <<
"the full tree once, then query efficiently.\n\n";
399 cout <<
"▶ Method A: compute_min_paths_tree()\n";
403 dijkstra.compute_min_paths_tree(g, source, tree);
406 cout <<
" Tree nodes: " << tree.get_num_nodes() <<
"\n";
407 cout <<
" Tree edges: " << tree.get_num_arcs() <<
"\n";
411 cout <<
" Distances from " << source->get_info() <<
":\n";
412 for (
size_t i = 1; i <
nodes.size(); ++i)
417 << right <<
": " <<
setw(6) << d <<
" km\n";
422 cout <<
"\n▶ Method B: paint_min_paths_tree()\n";
423 cout <<
" (More memory-efficient, marks graph directly)\n";
426 dijkstra.paint_min_paths_tree(g, source);
434 cout <<
" Distance to " <<
dest->get_info() <<
": " << d <<
" km\n";
441 cout <<
"\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
442 cout <<
"Part 3: Performance Comparison - Heap Types\n";
443 cout <<
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
445 cout <<
"\nDijkstra can use different priority queue implementations:\n";
446 cout <<
" • Binary Heap (default): O((V+E) log V) - good for sparse graphs\n";
447 cout <<
" • Fibonacci Heap: O(E + V log V) - better for dense graphs\n\n";
461 auto* s =
sparse.get_first_node();
487 cout <<
" Edges: " <<
sparse.get_num_arcs() <<
"\n";
495 auto* s =
dense.get_first_node();
521 cout <<
" Edges: " <<
dense.get_num_arcs() <<
"\n";
528 cout <<
"\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
529 cout <<
"Part 4: Special Cases\n";
530 cout <<
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
533 cout <<
"\n▶ Case A: Source = Destination (same node)\n";
536 double d =
dijkstra.find_min_path(g, source, source, p);
538 if (d == std::numeric_limits<double>::max() && p.
size() == 0)
540 cout <<
" Aleph-w behavior: start==end returns Inf and an empty path.\n";
541 cout <<
" If you want a trivial path, handle it explicitly as distance=0 and path=[start].\n";
545 cout <<
" Distance: " << d <<
" km\n";
546 cout <<
" Path length: " << p.
size() <<
" cities\n";
551 cout <<
"\n▶ Case B: Disconnected graph (unreachable node)\n";
567 cout <<
" Reachable nodes (in tree): " << tree.get_num_nodes() <<
"\n";
571 cout <<
"\n▶ Case C: Single-node graph\n";
580 cout <<
" Tree nodes: " << tree.get_num_nodes() <<
"\n";
587 cout <<
"\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
589 cout <<
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
592┌─────────────────────────────────────────────────────────────────────┐
593│ Dijkstra's Algorithm Properties │
594├─────────────────────────────────────────────────────────────────────┤
596│ • Binary Heap: O((V + E) log V) │
597│ • Fibonacci Heap: O(E + V log V) │
599│ Space Complexity: O(V) │
602│ • All edge weights must be non-negative │
603│ • For negative weights, use Bellman-Ford │
604├─────────────────────────────────────────────────────────────────────┤
606│ • find_min_path(g, src, dst, path) - single destination │
607│ • compute_min_paths_tree(g, src, tree) - build full tree │
608│ • paint_min_paths_tree(g, src) - mark graph in-place │
609│ • get_min_path(dst, path) - query after paint │
610│ • get_min_path(tree, dst, path) - query from tree │
611│ • get_distance(dst) - just the distance after paint │
612├─────────────────────────────────────────────────────────────────────┤
614│ • Single shortest path: find_min_path() │
615│ • Multiple queries from same source: compute/paint tree first │
616│ • Memory-constrained: paint_min_paths_tree() │
617│ • Need actual tree structure: compute_min_paths_tree() │
618└─────────────────────────────────────────────────────────────────────┘
621 cout << "\nFor graphs with heuristic information, consider using A* (AStar.H)\n";
622 cout <<
"which can be significantly faster for single-destination queries.\n\n";
Dijkstra's shortest path algorithm.
Generic directed graph (digraph) wrapper template.
typename BaseGraph::Arc Arc
typename BaseGraph::Node Node
Spanning tree calculation of all shortest paths from a given node according to Dijkstra's algorithm.
GT::Node * compute_min_paths_tree(const GT &g, typename GT::Node *start, GT &tree)
Computes the spanning tree of all shortest paths from the start node.
void for_each_node(Operation op=Operation()) const
Execute an operation on each node of path.
size_t size() const noexcept
Return the path length in nodes.
void for_each_arc(Operation op=Operation()) const
Execute an operation on each arc of path.
List_Digraph< CityNode, RoadArc > CityGraph
Graph type: directed graph of cities connected by roads.
double measure_time_ms(Func &&f)
CityGraph build_city_graph(vector< CityGraph::Node * > &nodes)
Build a sample graph representing a city road network.
void print_graph(CityGraph &g)
Print the graph structure.
CityGraph build_random_graph(int num_nodes, double edge_probability, double max_weight, unsigned seed=42)
Build a random graph for performance testing.
void print_path_detailed(CityGraph &g, Path< CityGraph > &path)
Print a path with detailed step-by-step information.
DynArray< Graph::Node * > nodes
Main namespace for Aleph-w library functions.
std::string to_string(const time_t t, const std::string &format)
Format a time_t value into a string using format.
DynList< T > maps(const C &c, Op op)
Classic map operation.
Default filter for filtered iterators on arcs.
Node belonging to a graph implemented with a double linked adjacency list.
Filtered iterator of adjacent arcs of a node.
Distance accessor functor for Dijkstra algorithm.
double operator()(CityGraph::Arc *arc) const
Generic graph and digraph implementations.