The Boost Graph Library

The Boost Graph Library: User Guide and Reference Manual · Jeremy G. Siek, Lie-Quan Lee & Andrew Lumsdaine ·300 pages

Generic C++ graph library: adjacency_list/adjacency_matrix graph classes, BFS/DFS/topological sort/Dijkstra/Bellman-Ford/Kruskal algorithms, property maps, visitor customization hooks, and the concepts-and-models generic programming design pattern that makes all BGL types interoperable.

Capabilities (6)
  • Choose adjacency_list vs adjacency_matrix based on graph density and access patterns
  • Build directed/undirected graphs with vertex and edge properties using BGL adjacency_list
  • Run BFS, DFS, topological sort, Dijkstra, Bellman-Ford, and Kruskal with BGL algorithms
  • Customize BGL algorithms with visitor event-point callbacks (discover_vertex, tree_edge, finish_vertex)
  • Use property maps to attach and read vertex/edge attributes in generic algorithms
  • Reason about concepts vs inheritance: when to use templates over virtual functions for zero-overhead abstraction
How to use

Install this skill and Claude can build BGL adjacency_list graphs with vertex and edge properties, run any standard graph algorithm (BFS, DFS, Dijkstra, Bellman-Ford, Kruskal, topological sort), and implement custom visitor structs to hook into event points like back_edge and finish_vertex

Why it matters

Gives Claude a complete, production-ready C++ toolkit for graph problems — routing, dependency resolution, spanning trees, cycle detection — without requiring a custom graph implementation every time, while also demonstrating zero-overhead generic programming via templates over virtual dispatch

Example use cases
  • Modeling a build system's task dependencies as a directed graph and producing a valid build order using topological_sort while detecting circular dependencies via a DFS back_edge visitor
  • Running dijkstra_shortest_paths from a source node over a weighted network graph and returning the minimum-cost path and total distance to every reachable vertex
  • Computing the minimum spanning tree of a network topology using kruskal_minimum_spanning_tree and outputting the subset of edges that connects all nodes at minimum total weight

Boost Graph Library (BGL) Skill

Graph Representation Selection

adjacency_list (primary BGL graph class)

#include <boost/graph/adjacency_list.hpp>
using namespace boost;

// Template parameters:
// adjacency_list<OutEdgeList, VertexList, Directed,
//                VertexProperties, EdgeProperties, GraphProperties>

// Directed graph with vertex and edge properties
typedef adjacency_list<
    vecS,          // OutEdgeList: vector (fast traversal, allows parallel edges)
    vecS,          // VertexList: vector (O(1) access by index)
    directedS,     // or undirectedS, bidirectionalS
    property<vertex_name_t, std::string>,       // vertex property
    property<edge_weight_t, double>             // edge property
> Graph;

// Container options for EdgeList/VertexList:
// vecS    → vector: fast O(1) access, allows parallel edges
// listS   → list: fast insert/remove, no parallel edge removal
// setS    → set: no parallel edges, O(log n) insert
// multisetS → multiset: allows parallel edges, O(log n)

adjacency_matrix (dense graphs)

#include <boost/graph/adjacency_matrix.hpp>

// Use when |E| ≈ |V|²
// O(1) edge existence check: edge(u, v, g).second
typedef adjacency_matrix<
    directedS,
    property<vertex_name_t, std::string>,
    property<edge_weight_t, double>
> DenseGraph;

Directed Options

TypeOut-edgesIn-edgesUse when
directedSYesNoOne-way traversal only
undirectedSYes (both dirs)N/AUndirected graphs
bidirectionalSYesYesNeed in_edges() access

Building a Graph

typedef adjacency_list<vecS, vecS, directedS> Graph;
typedef graph_traits<Graph>::vertex_descriptor Vertex;
typedef graph_traits<Graph>::edge_descriptor Edge;

Graph g;

// Add vertices
Vertex a = add_vertex(g);
Vertex b = add_vertex(g);
Vertex c = add_vertex(g);

// Add edges
add_edge(a, b, g);
add_edge(b, c, g);
add_edge(a, c, g);

// Query
num_vertices(g);        // vertex count
num_edges(g);           // edge count

// Iteration
auto [vi, vi_end] = vertices(g);
for (; vi != vi_end; ++vi) { /* *vi is a Vertex */ }

auto [ei, ei_end] = edges(g);
for (; ei != ei_end; ++ei) {
    source(*ei, g);  target(*ei, g);
}

auto [oi, oi_end] = out_edges(a, g);  // out-edges of vertex a

Property Maps

// Internal properties (stored in graph)
typedef adjacency_list<vecS, vecS, directedS,
    property<vertex_name_t, std::string>,
    property<edge_weight_t, double>> Graph;

Graph g;
auto name_map   = get(vertex_name,   g);
auto weight_map = get(edge_weight,   g);

Vertex v = add_vertex(g);
put(name_map, v, "router-A");

auto [e, ok] = add_edge(a, b, g);
put(weight_map, e, 1.5);

// Get value
std::string n = get(name_map, v);
double w      = get(weight_map, e);

// External property maps (for algorithms that need scratch space)
std::vector<default_color_type> color(num_vertices(g));
auto color_map = make_iterator_property_map(color.begin(), get(vertex_index, g));

Graph Algorithms

Breadth-First Search (BFS)

#include <boost/graph/breadth_first_search.hpp>

// Simple usage
std::vector<Vertex> pred(num_vertices(g));
breadth_first_search(g, source_vertex,
    visitor(make_bfs_visitor(record_predecessors(&pred[0], on_tree_edge()))));

// Custom visitor
struct MyBFSVisitor : public default_bfs_visitor {
    template <typename V, typename G>
    void discover_vertex(V u, const G&) const {
        std::cout << u << '\n';
    }
    template <typename E, typename G>
    void examine_edge(E e, const G& g) const { /* ... */ }
};
breadth_first_search(g, start, visitor(MyBFSVisitor{}));

Depth-First Search (DFS)

#include <boost/graph/depth_first_search.hpp>

struct MyDFSVisitor : public default_dfs_visitor {
    template <typename V, typename G>
    void finish_vertex(V u, const G&) const {
        // Called when all descendants processed — use for topological sort
        result.push_back(u);
    }
};
depth_first_search(g, visitor(MyDFSVisitor{}));

Topological Sort

#include <boost/graph/topological_sort.hpp>

std::deque<Vertex> order;
topological_sort(g, std::front_inserter(order));
// order is now in topological order (u before v if edge u→v)
// Throws boost::not_a_dag if graph has cycles

Shortest Paths (Dijkstra)

#include <boost/graph/dijkstra_shortest_paths.hpp>

std::vector<double> dist(num_vertices(g));
std::vector<Vertex> pred(num_vertices(g));

dijkstra_shortest_paths(g, source_v,
    predecessor_map(make_iterator_property_map(pred.begin(), get(vertex_index, g)))
    .distance_map(make_iterator_property_map(dist.begin(), get(vertex_index, g)))
    .weight_map(get(edge_weight, g)));

// Reconstruct path from source to target:
Vertex cur = target_v;
while (cur != source_v) {
    path.push_back(cur);
    cur = pred[cur];
}
path.push_back(source_v);
std::reverse(path.begin(), path.end());

Bellman-Ford (negative weights)

#include <boost/graph/bellman_ford_shortest_paths.hpp>

bool no_neg_cycle = bellman_ford_shortest_paths(
    g, num_vertices(g),
    weight_map(get(edge_weight, g))
    .predecessor_map(&pred[0])
    .distance_map(&dist[0]));

Minimum Spanning Tree (Kruskal)

#include <boost/graph/kruskal_min_spanning_tree.hpp>

std::vector<Edge> mst_edges;
kruskal_minimum_spanning_tree(g, std::back_inserter(mst_edges),
    weight_map(get(edge_weight, g)));

Visitor Event Points

BFS EventDFS EventWhen triggered
initialize_vertexinitialize_vertexBefore search
discover_vertexstart_vertexFirst visit to vertex
examine_vertexdiscover_vertexPopped from queue
examine_edgeexamine_edgeEdge about to be explored
tree_edgetree_edgeEdge in search tree
non_tree_edgeback_edgeBack edge (DFS cycle detection)
finish_vertexAll descendants done

Generic Programming Concepts (BGL Design Philosophy)

Concept vs Inheritance

OOP polymorphism (virtual functions):
+ Run-time dispatch
- Extra pointer dereference → cannot inline → slower for fine-grained ops
- Binary method problem (operator== between derived types requires downcast)

Generic programming (templates / concepts):
+ Compile-time dispatch → inlinable → zero overhead
+ No binary method problem — types need not inherit from base
+ Any type satisfying the requirements works (structural, not nominal)
- Larger binary (template instantiation per type)
- Errors harder to read (before C++20 concepts)

Concept → Model pattern

// A concept is a set of requirements documented/enforced:
// VertexListGraph concept requires: vertices(g), num_vertices(g), etc.

// Any type that satisfies these requirements is a "model" of the concept:
// adjacency_list models VertexListGraph
// std::vector<std::list<int>> models VertexListGraph (via adaptor)
// LEDA Graph models VertexListGraph (via adaptor functions)

Traits Classes

// Access associated types for any graph type G:
graph_traits<G>::vertex_descriptor    // type of vertex handle
graph_traits<G>::edge_descriptor      // type of edge handle
graph_traits<G>::vertex_iterator      // type of vertex iterator
graph_traits<G>::edge_iterator        // type of edge iterator
graph_traits<G>::out_edge_iterator    // type of out-edge iterator
graph_traits<G>::directed_category    // directed_tag or undirected_tag
graph_traits<G>::edges_size_type      // integer type for edge count

Algorithm Selection Guide

ProblemAlgorithmHeader
Shortest paths (non-negative weights)dijkstra_shortest_pathsdijkstra_shortest_paths.hpp
Shortest paths (negative weights)bellman_ford_shortest_pathsbellman_ford_shortest_paths.hpp
All-pairs shortest pathsjohnson_all_pairs_shortest_pathsjohnson_all_pairs_shortest_paths.hpp
Minimum spanning treekruskal_minimum_spanning_tree or prim_minimum_spanning_treekruskal.hpp / prim.hpp
Topological orderingtopological_sorttopological_sort.hpp
Connected componentsconnected_componentsconnected_components.hpp
Strongly connected componentsstrong_componentsstrong_components.hpp
Cycle detectionDFS visitor detecting back_edgedepth_first_search.hpp
ReachabilityBFS from source, check colorbreadth_first_search.hpp