C++ Boost

edmunds_karp_max_flow

Graphs: directed
Properties: edge capacity, edge residual capacity, reverse edge, (vertex index | edge predecessor of vertex, vertex color)
Complexity: time: O(V E2) or O(V E U) if capacity values are integers bounded by U

  (1)
  template <typename VertexListGraph, 
            typename CapacityEdgeMap, typename ResidualCapacityEdgeMap,
            typename ReverseEdgeMap, typename VertexIndexMap>
  typename property_traits<CapacityEdgeMap>::value_type
  edmunds_karp_max_flow
    (VertexListGraph& g, 
     typename graph_traits<VertexListGraph>::vertex_descriptor src,
     typename graph_traits<VertexListGraph>::vertex_descriptor sink,
     CapacityEdgeMap cap, 
     ResidualCapacityEdgeMap res,
     ReverseEdgeMap rev, 
     VertexIndexMap index_map)

  (2)
  template <typename VertexListGraph, 
            typename CapacityEdgeMap, typename ResidualCapacityEdgeMap,
            typename ReverseEdgeMap, typename ColorMap, typename PredEdgeMap>
  typename property_traits<CapacityEdgeMap>::value_type
  edmunds_karp_max_flow
    (VertexListGraph& g, 
     typename graph_traits<VertexListGraph>::vertex_descriptor src,
     typename graph_traits<VertexListGraph>::vertex_descriptor sink,
     CapacityEdgeMap cap, 
     ResidualCapacityEdgeMap res,
     ReverseEdgeMap rev, 
     ColorMap color, 
     PredEdgeMap pred)

The edmunds_karp_max_flow() function calculates 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.

The algorithm is due to Edmonds and Karp, though we are using the variation called the ``labeling algorithm'' described in Network Flows.

This algorithm provides a very simple an easy to implement solution to the maximum flow problem. However, there are several reasons why this algorithm is not as good as the push_relabel_max_flow() algorithm.

Where Defined

boost/graph/edmunds_karp_max_flow.hpp

Parameters

For version 1:

For version 2 (all of the above, minus the vertex index map, plus the following):

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/edmunds_karp_max_flow.cpp.
#include <boost/config.hpp>
#include <iostream>
#include <string>
#include <boost/graph/edmunds_karp_map_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_residual_capacity_t>::type 
    residual_capacity = get(edge_residual_capacity, g);
  property_map<Graph, edge_reverse_t>::type 
    reverse_edge = get(edge_reverse, g);

  Traits::vertex_descriptor s, t;
  read_dimacs_max_flow(g, capacity, residual_capacity, reverse_edge, s, t);

  flow = edmunds_karp_max_flow(g, s, t, capacity, residual_capacity,
                               reverse_edge, get(vertex_index, g));

  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 (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
    for (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

See Also

push_relabel_max_flow().

Copyright © 2000 Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu)