C++ Boost

Running Graph Algorithms

BGL provides over 80 graph algorithms covering common graph problems. This page shows you how to use them effectively.

Quick Example: Dijkstra's Shortest Path

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <vector>

using namespace boost;

int main()
{
    // Create weighted graph
    typedef adjacency_list<vecS, vecS, directedS,
        no_property,
        property<edge_weight_t, int> > Graph;
    
    typedef std::pair<int, int> Edge;
    Edge edges[] = {Edge(0,1), Edge(0,2), Edge(1,3), Edge(2,3)};
    int weights[] = {5, 3, 2, 7};
    
    Graph g(edges, edges + 4, weights, 4);
    
    // Storage for results
    std::vector<int> distances(num_vertices(g));
    std::vector<graph_traits<Graph>::vertex_descriptor> predecessors(num_vertices(g));
    
    // Run Dijkstra from vertex 0
    dijkstra_shortest_paths(g, 0,
        distance_map(&distances[0])
        .predecessor_map(&predecessors[0]));
    
    // Print results
    for (int i = 0; i < distances.size(); ++i) {
        std::cout << "Distance to " << i << ": " << distances[i] << "\n";
    }
    
    return 0;
}

Common Algorithm Categories

CategoryExamples
Search breadth_first_search, depth_first_search, A*
Shortest Paths dijkstra_shortest_paths, bellman_ford_shortest_paths, floyd_warshall_all_pairs_shortest_paths
Minimum Spanning Tree kruskal_minimum_spanning_tree, prim_minimum_spanning_tree
Connected Components connected_components, strongly_connected_components, biconnected_components
Maximum Flow push_relabel_max_flow, edmonds_karp_max_flow, boykov_kolmogorov_max_flow
Matching maximum_weighted_matching, max_cardinality_matching
Centrality betweenness_centrality, closeness_centrality
Topological Sort topological_sort, dag_shortest_paths

Using Named Parameters

Most BGL algorithms use named parameters for flexibility. This allows you to specify only the parameters you need:

// Basic call - uses default parameters
dijkstra_shortest_paths(g, start_vertex);

// With distance map
dijkstra_shortest_paths(g, start_vertex,
    distance_map(&distances[0]));

// With multiple parameters  
dijkstra_shortest_paths(g, start_vertex,
    distance_map(&distances[0])
    .predecessor_map(&predecessors[0])
    .weight_map(get(edge_weight, g)));

Parameters are chained using the . operator.

Example: Breadth-First Search

#include <boost/graph/breadth_first_search.hpp>
#include <vector>

typedef adjacency_list<vecS, vecS, undirectedS> Graph;

int main()
{
    Graph g(5);
    add_edge(0, 1, g);
    add_edge(0, 2, g);
    add_edge(1, 3, g);
    add_edge(2, 4, g);
    
    // Storage for BFS state
    std::vector<default_color_type> colors(num_vertices(g));
    std::vector<int> distances(num_vertices(g));
    std::vector<graph_traits<Graph>::vertex_descriptor> predecessors(num_vertices(g));
    
    // Run BFS from vertex 0
    breadth_first_search(g, 0,
        visitor(make_bfs_visitor(
            std::make_pair(record_distances(&distances[0], on_tree_edge()),
            record_predecessors(&predecessors[0], on_tree_edge()))))
        .color_map(&colors[0]));
    
    return 0;
}

Example: Minimum Spanning Tree

#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <vector>

typedef adjacency_list<vecS, vecS, undirectedS,
    no_property,
    property<edge_weight_t, int> > Graph;

int main()
{
    typedef std::pair<int, int> Edge;
    Edge edges[] = {
        Edge(0,1), Edge(0,3), Edge(1,2),
        Edge(1,3), Edge(2,3), Edge(3,4)
    };
    int weights[] = {1, 4, 2, 5, 3, 7};
    
    Graph g(edges, edges + 6, weights, 5);
    
    // Storage for MST edges
    std::vector<graph_traits<Graph>::edge_descriptor> mst_edges;
    
    // Compute MST
    kruskal_minimum_spanning_tree(g, std::back_inserter(mst_edges));
    
    // Print MST
    std::cout << "MST edges:\n";
    for (auto e : mst_edges) {
        std::cout << "(" << source(e, g) << "," 
                  << target(e, g) << ")\n";
    }
    
    return 0;
}

Example: Connected Components

#include <boost/graph/connected_components.hpp>
#include <vector>

typedef adjacency_list<vecS, vecS, undirectedS> Graph;

int main()
{
    Graph g(7);
    // Create three components
    add_edge(0, 1, g);
    add_edge(1, 2, g);
    add_edge(3, 4, g);
    add_edge(5, 6, g);
    
    std::vector<int> component(num_vertices(g));
    int num_components = connected_components(g, &component[0]);
    
    std::cout << "Number of components: " << num_components << "\n";
    for (int i = 0; i < component.size(); ++i) {
        std::cout << "Vertex " << i << " in component " 
                  << component[i] << "\n";
    }
    
    return 0;
}

Example: Topological Sort

#include <boost/graph/topological_sort.hpp>
#include <list>

typedef adjacency_list<vecS, vecS, directedS> Graph;

int main()
{
    Graph g(6);
    // Dependencies: 0<-1, 0<-2, 1<-3, 2<-3, 3<-4, 4<-5
    add_edge(1, 0, g);
    add_edge(2, 0, g);
    add_edge(3, 1, g);
    add_edge(3, 2, g);
    add_edge(4, 3, g);
    add_edge(5, 4, g);
    
    std::list<int> sorted_vertices;
    topological_sort(g, std::front_inserter(sorted_vertices));
    
    std::cout << "Topological order: ";
    for (auto v : sorted_vertices) {
        std::cout << v << " ";
    }
    std::cout << "\n";
    
    return 0;
}

Using Visitors for Custom Behavior

Visitors let you customize algorithm behavior by providing callbacks at specific points:

#include <boost/graph/depth_first_search.hpp>

// Custom visitor to count back edges
struct cycle_detector : public dfs_visitor<>
{
    cycle_detector(bool& has_cycle) : m_has_cycle(has_cycle) {}
    
    template <class Edge, class Graph>
    void back_edge(Edge, Graph&) {
        m_has_cycle = true;
    }
    
    bool& m_has_cycle;
};

int main()
{
    Graph g(4);
    add_edge(0, 1, g);
    add_edge(1, 2, g);
    add_edge(2, 3, g);
    add_edge(3, 1, g);  // Creates a cycle
    
    bool has_cycle = false;
    depth_first_search(g, visitor(cycle_detector(has_cycle)));
    
    std::cout << (has_cycle ? "Graph has cycles" : "Graph is acyclic") << "\n";
    
    return 0;
}

Property Maps in Algorithms

Most algorithms work with property maps to access graph data:

// Internal property map (built into graph)
auto weight_map = get(edge_weight, g);
dijkstra_shortest_paths(g, start, weight_map(weight_map));

// External property map (separate storage)
std::vector<int> weights(num_edges(g));
auto weight_map = make_iterator_property_map(weights.begin(), get(edge_index, g));
dijkstra_shortest_paths(g, start, weight_map(weight_map));

Common Patterns

Pattern: Recording Algorithm Results

std::vector<int> distances(num_vertices(g));
std::vector<Vertex> predecessors(num_vertices(g));

dijkstra_shortest_paths(g, start,
    distance_map(&distances[0])
    .predecessor_map(&predecessors[0]));

// Reconstruct path from start to target
std::vector<Vertex> path;
Vertex current = target;
while (current != start) {
    path.push_back(current);
    current = predecessors[current];
}
path.push_back(start);
std::reverse(path.begin(), path.end());

Pattern: Checking Preconditions

// Check if graph is DAG before topological sort
bool has_cycle = false;
depth_first_search(g, visitor(cycle_detector(has_cycle)));

if (!has_cycle) {
    topological_sort(g, std::front_inserter(result));
} else {
    std::cerr << "Cannot sort: graph has cycles\n";
}

Algorithm Reference by Problem

ProblemAlgorithm
Find shortest pathdijkstra_shortest_paths
Shortest paths with negative weightsbellman_ford_shortest_paths
All pairs shortest pathsfloyd_warshall_all_pairs_shortest_paths
Find minimum spanning treekruskal_minimum_spanning_tree
Maximum network flowpush_relabel_max_flow
Detect cyclesdepth_first_search + visitor
Find connected componentsconnected_components
Task scheduling ordertopological_sort
Find bridges/articulation pointsbiconnected_components

For a complete list of algorithms, see the Table of Contents under the Algorithms section.

Copyright © 2000-2001 Jeremy Siek, Indiana University