Push-Relabel Maximum Flow
Calculates the maximum flow of a network using the push-relabel algorithm.
Complexity: O(V3)
Defined in: <boost/graph/push_relabel_max_flow.hpp>
Example
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/push_relabel_max_flow.hpp>
#include <iostream>
using namespace boost;
using Traits = adjacency_list_traits<vecS, vecS, directedS>;
struct Edge {
int capacity;
int residual_capacity;
Traits::edge_descriptor reverse;
};
using Graph = adjacency_list<vecS, vecS, directedS, no_property, Edge>;
using Descriptor = graph_traits<Graph>::edge_descriptor;
using Vertex = graph_traits<Graph>::vertex_descriptor;
void add_flow_edge(Graph& g, int from, int to, int cap) {
Descriptor e = add_edge(from, to, g).first;
Descriptor r = add_edge(to, from, g).first;
g[e].capacity = cap; g[e].reverse = r;
g[r].capacity = 0; g[r].reverse = e;
}
int main() {
Graph g(4);
add_flow_edge(g, 0, 1, 10);
add_flow_edge(g, 0, 2, 10);
add_flow_edge(g, 1, 3, 5);
add_flow_edge(g, 2, 3, 15);
add_flow_edge(g, 1, 2, 4);
int flow = push_relabel_max_flow(g, Vertex(0), Vertex(3),
get(&Edge::capacity, g),
get(&Edge::residual_capacity, g),
get(&Edge::reverse, g),
get(vertex_index, g));
std::cout << "Push-relabel max flow: " << flow << "\n";
}
Push-relabel max flow: 19
(1) Positional version
template <class Graph,
class CapacityEdgeMap, class ResidualCapacityEdgeMap,
class ReverseEdgeMap, class VertexIndexMap>
typename property_traits<CapacityEdgeMap>::value_type push_relabel_max_flow(
Graph& g,
typename graph_traits<Graph>::vertex_descriptor src,
typename graph_traits<Graph>::vertex_descriptor sink,
CapacityEdgeMap cap, ResidualCapacityEdgeMap res,
ReverseEdgeMap rev, VertexIndexMap index_map)
| Direction | Parameter | Description |
|---|---|---|
IN |
|
A directed graph. The graph’s type must be a model of Vertex List Graph. For each edge (u,v) in the graph, the reverse edge (v,u) must also be in the graph. |
IN |
|
The source vertex for the flow network graph. |
IN |
|
The sink vertex for the flow network graph. |
IN |
|
The edge capacity property map. The type must be a model of a constant Lvalue Property Map. The key type of the map must be the graph’s edge descriptor type. |
OUT |
|
The edge residual capacity property map. The type must be a model of a mutable Lvalue Property Map. The key type of the map must be the graph’s edge descriptor type. |
IN |
|
An edge property map that maps every edge (u,v) in the graph to the reverse edge (v,u). The map must be a model of constant Lvalue Property Map. The key type of the map must be the graph’s edge descriptor type. |
IN |
|
Maps each vertex of the graph to a unique integer in the range
|
(2) Named parameter version
template <class Graph, class P, class T, class R>
typename property_traits<CapacityEdgeMap>::value_type push_relabel_max_flow(
Graph& g,
typename graph_traits<Graph>::vertex_descriptor src,
typename graph_traits<Graph>::vertex_descriptor sink,
const bgl_named_params<P, T, R>& params = all defaults)
| Direction | Parameter | Description |
|---|---|---|
IN |
|
A directed graph. Must model Vertex List Graph. For each edge (u,v) in the graph, the reverse edge (v,u) must also be in the graph. |
IN |
|
The source vertex for the flow network graph. |
IN |
|
The sink vertex for the flow network graph. |
IN |
|
Named parameters passed via |
| Direction | Named Parameter | Description / Default |
|---|---|---|
IN |
|
The edge capacity property map. The type must be a model of a constant
Lvalue Property Map.
The key type of the map must be the graph’s edge descriptor type. |
OUT |
|
The edge residual capacity property map. The type must be a model of a
mutable Lvalue Property Map.
The key type of the map must be the graph’s edge descriptor type. |
IN |
|
An edge property map that maps every edge (u,v) in the graph to the
reverse edge (v,u). The map must be a model of constant
Lvalue Property Map.
The key type of the map must be the graph’s edge descriptor type. |
IN |
|
Maps each vertex of the graph to a unique integer in the range
|
Description
The push_relabel_max_flow() function implements the
push-relabel algorithm
to calculate the maximum flow of a network. See Section
Network Flow
Algorithms for a description of maximum flow. The calculated maximum
flow will be the return value of the function. The function also
calculates the flow values f(u,v) for all (u,v) in E, which are
returned in the form of the residual capacity r(u,v) = c(u,v) - f(u,v).
There are several special requirements on the input graph and property
map parameters for this algorithm. First, the directed graph G=(V,E)
that represents the network must be augmented to include the reverse
edge for every edge in E. That is, the input graph should be Gin =
(V,{E U ET}). The ReverseEdgeMap argument rev must map each
edge in the original graph to its reverse edge, that is (u,v) → (v,u)
for all (u,v) in E. The CapacityEdgeMap argument cap must map
each edge in E to a positive number, and each edge in ET to 0.
This algorithm was developed by Goldberg.
Example
This reads in an example maximum flow problem (a graph with edge
capacities) from a file in the DIMACS format. The source for this
example can be found in example/max_flow.cpp.
#include <boost/config.hpp>
#include <iostream>
#include <string>
#include <boost/graph/push_relabel_max_flow.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/read_dimacs.hpp>
int
main()
{
using namespace boost;
typedef adjacency_list_traits<vecS, vecS, directedS> Traits;
typedef adjacency_list<vecS, vecS, directedS,
property<vertex_name_t, std::string>,
property<edge_capacity_t, long,
property<edge_residual_capacity_t, long,
property<edge_reverse_t, Traits::edge_descriptor> > >
> Graph;
Graph g;
long flow;
property_map<Graph, edge_capacity_t>::type
capacity = get(edge_capacity, g);
property_map<Graph, edge_reverse_t>::type
rev = get(edge_reverse, g);
property_map<Graph, edge_residual_capacity_t>::type
residual_capacity = get(edge_residual_capacity, g);
Traits::vertex_descriptor s, t;
read_dimacs_max_flow(g, capacity, rev, s, t);
flow = push_relabel_max_flow(g, s, t);
std::cout << "c The total flow:" << std::endl;
std::cout << "s " << flow << std::endl << std::endl;
std::cout << "c flow values:" << std::endl;
graph_traits<Graph>::vertex_iterator u_iter, u_end;
graph_traits<Graph>::out_edge_iterator ei, e_end;
for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
if (capacity[*ei] > 0)
std::cout << "f " << *u_iter << " " << target(*ei, g) << " "
<< (capacity[*ei] - residual_capacity[*ei]) << std::endl;
return 0;
}
The output is:
c The total flow: s 4 c flow values: f 0 1 4 f 1 2 4 f 2 3 2 f 2 4 2 f 3 1 0 f 3 6 2 f 4 5 3 f 5 6 0 f 5 7 3 f 6 4 1 f 6 7 1