- Overview
- Algorithm Catalog
- Shortest Paths
- Traversal
- Components
- Minimum Spanning Trees
- Graph Analytics
- Common Infrastructure
- Roadmap
All graph-v3 algorithms require a graph satisfying the adjacency_list<G>
concept. This supports two families of vertex storage:
- Index-based (
index_adjacency_list<G>) — contiguous, integer-indexed random-access containers (dynamic_graphwith vector/deque vertices,compressed_graph,undirected_adjacency_list, or any range-of-ranges) - Map-based (
mapped_adjacency_list<G>) — sparse vertex ID containers (dynamic_graphwithmap/unordered_mapvertices) where vertex IDs need not be contiguous
For map-based graphs, algorithm output parameters (distances, predecessors,
component labels, etc.) should be vertex property maps created via
make_vertex_property_map<G, T>(g, init_value) instead of pre-sized vectors.
Algorithms follow a consistent pattern:
- Input: graph
g, source vertex (or vertices), and optional parameters - Output: filled via caller-provided output ranges (distances, predecessors, component labels) — not returned by value
- Weight functions: passed as callable
WF(g, uv)returning edge weight - Visitors: optional structs with callback methods for fine-grained event hooks
- Initialization: use
init_shortest_paths()to properly set up distance and predecessor vectors before calling shortest-path algorithms
Bidirectional graphs: Algorithms that benefit from incoming-edge access (e.g., Kosaraju SCC, transpose graph) can use bidirectional
dynamic_graphcontainers. Search views (BFS, DFS, topological sort) also accept anin_edge_accessorfor reverse traversal — see Bidirectional Access.
#include <graph/algorithm/dijkstra_shortest_paths.hpp>
// Index-based graph: use pre-sized vectors
std::vector<int> distance(num_vertices(g));
std::vector<size_t> predecessor(num_vertices(g));
init_shortest_paths(distance, predecessor);
dijkstra_shortest_paths(g, 0, distance, predecessor,
[](const auto& g, const auto& uv) { return edge_value(g, uv); });#include <graph/algorithm/dijkstra_shortest_paths.hpp>
#include <graph/adj_list/vertex_property_map.hpp>
// Map-based graph: use vertex property maps
using G = /* some mapped_adjacency_list graph */;
auto distances = make_vertex_property_map<G, int>(g, infinite_distance<int>());
auto predecessors = make_vertex_property_map<G, vertex_id_t<G>>(g, vertex_id_t<G>{});
for (auto&& [uid, u] : views::vertexlist(g))
predecessors[uid] = uid;
dijkstra_shortest_paths(g, source_id, distances, predecessors,
[](const auto& g, const auto& uv) { return edge_value(g, uv); });All headers are under include/graph/algorithm/.
Shortest Paths
| Algorithm | Header | Brief description | Time | Space |
|---|---|---|---|---|
| Bellman-Ford | bellman_ford_shortest_paths.hpp |
Shortest paths with negative weights; cycle detection | O(V·E) | O(1) |
| Dijkstra | dijkstra_shortest_paths.hpp |
Single/multi-source shortest paths (non-negative weights) | O((V+E) log V) | O(V) |
Traversal
| Algorithm | Header | Brief description | Time | Space |
|---|---|---|---|---|
| BFS | breadth_first_search.hpp |
Level-order traversal from source(s) | O(V+E) | O(V) |
| DFS | depth_first_search.hpp |
Depth-first traversal with edge classification | O(V+E) | O(V) |
| Topological Sort | topological_sort.hpp |
Linear ordering of DAG vertices | O(V+E) | O(V) |
Components
| Algorithm | Header | Brief description | Time | Space |
|---|---|---|---|---|
| Articulation Points | articulation_points.hpp |
Cut vertices whose removal disconnects the graph | O(V+E) | O(V) |
| Biconnected Components | biconnected_components.hpp |
Maximal 2-connected subgraphs (Hopcroft-Tarjan) | O(V+E) | O(V+E) |
| Connected Components | connected_components.hpp |
Undirected CC, directed SCC (Kosaraju), union-find (afforest) | O(V+E) | O(V) |
| Tarjan SCC | tarjan_scc.hpp |
Single-pass directed SCC via low-link values | O(V+E) | O(V) |
Minimum Spanning Trees
| Algorithm | Header | Brief description | Time | Space |
|---|---|---|---|---|
| Kruskal MST | mst.hpp |
Edge-list-based MST via union-find | O(E log E) | O(E+V) |
| Prim MST | mst.hpp |
Adjacency-list-based MST via priority queue | O(E log V) | O(V) |
Analytics
| Algorithm | Header | Brief description | Time | Space |
|---|---|---|---|---|
| Jaccard Coefficient | jaccard.hpp |
Pairwise neighbor-set similarity per edge | O(V + E·d) | O(V+E) |
| Label Propagation | label_propagation.hpp |
Community detection via majority-vote labels | O(E) per iter | O(V) |
| Maximal Independent Set | mis.hpp |
Greedy MIS (non-adjacent vertex set) | O(V+E) | O(V) |
| Triangle Count | tc.hpp |
Count 3-cliques via sorted-list intersection | O(m^{3/2}) | O(1) |
| Algorithm | Category | Header | Time | Space |
|---|---|---|---|---|
| Articulation Points | Components | articulation_points.hpp |
O(V+E) | O(V) |
| Bellman-Ford | Shortest Paths | bellman_ford_shortest_paths.hpp |
O(V·E) | O(1) |
| BFS | Traversal | breadth_first_search.hpp |
O(V+E) | O(V) |
| Biconnected Components | Components | biconnected_components.hpp |
O(V+E) | O(V+E) |
| Connected Components | Components | connected_components.hpp |
O(V+E) | O(V) |
| Kosaraju SCC | Components | connected_components.hpp |
O(V+E) | O(V) |
| DFS | Traversal | depth_first_search.hpp |
O(V+E) | O(V) |
| Dijkstra | Shortest Paths | dijkstra_shortest_paths.hpp |
O((V+E) log V) | O(V) |
| Jaccard Coefficient | Analytics | jaccard.hpp |
O(V + E·d) | O(V+E) |
| Kruskal MST | MST | mst.hpp |
O(E log E) | O(E+V) |
| Label Propagation | Analytics | label_propagation.hpp |
O(E) per iter | O(V) |
| Maximal Independent Set | Analytics | mis.hpp |
O(V+E) | O(V) |
| Prim MST | MST | mst.hpp |
O(E log V) | O(V) |
| Topological Sort | Traversal | topological_sort.hpp |
O(V+E) | O(V) |
| Tarjan SCC | Components | tarjan_scc.hpp |
O(V+E) | O(V) |
| Triangle Count | Analytics | tc.hpp |
O(m^{3/2}) | O(1) |
Finds single-source or multi-source shortest paths in a graph with non-negative
edge weights using a binary-heap priority queue. Provides both dijkstra_shortest_paths
(distances + predecessors) and dijkstra_shortest_distances (distances only) variants.
Time: O((V+E) log V) — Space: O(V) — Header: dijkstra_shortest_paths.hpp
Finds shortest paths supporting negative edge weights and detects negative-weight
cycles. Returns std::optional<vertex_id_t<G>> — empty if no negative cycle, or a
vertex on the cycle. Use find_negative_cycle to extract the full cycle path.
Time: O(V·E) — Space: O(1) — Header: bellman_ford_shortest_paths.hpp
Explores vertices in level-order (FIFO) from one or more sources. Entirely visitor-driven — you provide callback methods for vertex/edge events. Supports single-source and multi-source variants.
Time: O(V+E) — Space: O(V) — Header: breadth_first_search.hpp
Performs iterative DFS with three-color marking (White/Gray/Black), enabling precise edge classification into tree, back, and forward/cross edges. Foundation for cycle detection, topological sorting, and SCC discovery.
Time: O(V+E) — Space: O(V) — Header: depth_first_search.hpp
Produces a linear ordering of vertices in a DAG such that for every edge (u,v),
u appears before v. Returns bool — false if a cycle is detected. Supports
full-graph, single-source, and multi-source variants.
Time: O(V+E) — Space: O(V) — Header: topological_sort.hpp
Three algorithms in one header: connected_components (DFS-based, undirected),
kosaraju (two-pass DFS for directed SCC, uses in_edge_accessor for the
reverse pass on bidirectional graphs), and afforest (union-find with neighbor
sampling, parallel-friendly).
Kosaraju’s algorithm works with any graph that supports both outgoing and
incoming edge iteration (i.e., bidirectional_adjacency_list concept).
A transpose_graph view is also available for algorithms that need a
transposed adjacency structure:
#include <graph/algorithm/connected_components.hpp>
#include <graph/algorithm/transpose_graph.hpp>Time: O(V+E) — Space: O(V) — Header: connected_components.hpp
Finds all maximal 2-connected subgraphs using the iterative Hopcroft-Tarjan algorithm. Articulation points appear in multiple components; bridges form their own 2-vertex components.
Time: O(V+E) — Space: O(V+E) — Header: biconnected_components.hpp
Finds cut vertices whose removal disconnects the graph, using the iterative Hopcroft-Tarjan algorithm with discovery times and low-link values. Each articulation point is emitted exactly once.
Time: O(V+E) — Space: O(V) — Header: articulation_points.hpp
Edge-list-based MST using sort + union-find. Returns {total_weight, num_components}.
Includes inplace_kruskal variant that sorts input in-place. Pass std::greater<>{}
for maximum spanning tree.
Time: O(E log E) — Space: O(E+V) — Header: mst.hpp
Adjacency-list-based MST using a priority queue. Grows the MST from a seed vertex, filling predecessor and weight arrays. Returns total MST weight.
Time: O(E log V) — Space: O(V) — Header: mst.hpp
Counts 3-cliques via merge-based sorted-list intersection. Requires adjacency lists
sorted by target ID (ordered_vertex_edges concept). Works with sorted-edge
containers (vos, dos) and undirected_adjacency_list.
Time: O(m^{3/2}) — Space: O(1) — Header: tc.hpp
Greedy MIS — finds a maximal set of non-adjacent vertices starting from a seed. Result is seed-dependent (different seeds may yield different-sized sets). Self-loops exclude a vertex from the MIS.
Time: O(V+E) — Space: O(V) — Header: mis.hpp
Computes pairwise neighbor-set similarity
Time: O(V + E·d) — Space: O(V+E) — Header: jaccard.hpp
Community detection via iterative majority-vote label propagation. Each vertex adopts the most frequent label among its neighbors until convergence. Supports partial labeling via an empty-label sentinel. Tie-breaking is random.
Time: O(E) per iteration — Space: O(V) — Header: label_propagation.hpp
All shortest-path algorithms share utilities from traversal_common.hpp:
| Utility | Purpose |
|---|---|
init_shortest_paths(distances) |
Set all distances to infinity |
init_shortest_paths(distances, predecessors) |
Set distances to infinity, predecessors to self |
infinite_distance<T>() |
Returns the "infinity" sentinel for type T |
zero_distance<T>() |
Returns the additive identity for type T |
Algorithms accept an optional visitor struct with callback methods. Only the callbacks you define are called — unimplemented callbacks are silently skipped.
Shortest-path visitor events:
| Event | Called when |
|---|---|
on_initialize_vertex(g, u) |
Before traversal starts, for each vertex |
on_discover_vertex(g, u) |
Vertex first reached |
on_examine_vertex(g, u) |
Vertex popped from queue |
on_examine_edge(g, uv) |
Edge examined |
on_edge_relaxed(g, uv) |
Edge improved a shorter path |
on_edge_not_relaxed(g, uv) |
Edge did not improve path |
on_edge_minimized(g, uv) |
Edge achieved final minimum (Bellman-Ford) |
on_edge_not_minimized(g, uv) |
Edge not at final minimum (Bellman-Ford) |
DFS-specific visitor events:
| Event | Called when |
|---|---|
on_start_vertex(g, u) |
DFS root vertex |
on_tree_edge(g, uv) |
Edge to unvisited vertex (White → Gray) |
on_back_edge(g, uv) |
Edge to ancestor (Gray vertex) |
on_forward_or_cross_edge(g, uv) |
Edge to already-finished vertex (Black) |
on_finish_edge(g, uv) |
All descendants of edge target explored |
on_finish_vertex(g, u) |
All adjacent edges explored |
Each callback also has an _id variant that receives vertex/edge IDs instead of
descriptors.
The following algorithms are planned but not yet implemented:
- A* search
- Bidirectional Dijkstra
- Johnson's all-pairs shortest paths
- Floyd-Warshall all-pairs shortest paths
- Maximum flow (push-relabel, Dinic's)
- Minimum cut
- Graph coloring
- Betweenness centrality
- PageRank
- Adjacency Lists User Guide — concepts and CPOs used by algorithms
- Views User Guide — lazy search views (DFS, BFS, topological sort)
- Containers User Guide — graph container options
- Getting Started — quick-start examples