Cycle Canceling for Min Cost Max Flow
Calculates the minimum cost flow of a network with given flow by iteratively canceling negative-cost cycles in the residual graph.
Complexity: O(C * |V| * |E|) for integer capacities/weights, where C is the initial flow cost
Defined in: <boost/graph/cycle_canceling.hpp>
Example
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/cycle_canceling.hpp>
#include <boost/graph/edmonds_karp_max_flow.hpp>
#include <boost/graph/find_flow_cost.hpp>
#include <iostream>
#include <vector>
using namespace boost;
using Traits = adjacency_list_traits<vecS, vecS, directedS>;
struct Edge {
int capacity;
int residual_capacity;
int weight;
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_edge_pair(Graph& g, int u, int v, int cap, int cost) {
Descriptor e = add_edge(u, v, g).first;
Descriptor r = add_edge(v, u, g).first;
g[e].capacity = cap; g[r].capacity = 0;
g[e].weight = cost; g[r].weight = -cost;
g[e].reverse = r; g[r].reverse = e;
}
int main() {
Graph g(4);
add_edge_pair(g, 0, 1, 2, 1);
add_edge_pair(g, 0, 2, 1, 3);
add_edge_pair(g, 1, 3, 2, 2);
add_edge_pair(g, 2, 3, 3, 1);
auto cap = get(&Edge::capacity, g);
auto res = get(&Edge::residual_capacity, g);
auto rev = get(&Edge::reverse, g);
auto wgt = get(&Edge::weight, g);
std::vector<default_color_type> color(num_vertices(g));
std::vector<Descriptor> pred(num_vertices(g));
std::vector<int> dist(num_vertices(g));
auto idx = get(vertex_index, g);
edmonds_karp_max_flow(g, Vertex(0), Vertex(3), cap, res, rev,
make_iterator_property_map(color.begin(), idx),
make_iterator_property_map(pred.begin(), idx));
cycle_canceling(g, wgt, rev, res,
make_iterator_property_map(pred.begin(), idx),
make_iterator_property_map(dist.begin(), idx));
int cost = find_flow_cost(g, cap, res, wgt);
std::cout << "Min cost: " << cost << "\n";
}
Min cost: 10
(1) Positional version
template <typename Graph, typename Pred, typename Distance,
typename Reversed, typename ResidualCapacity,
typename Weight>
void cycle_canceling(
const Graph& g,
Weight weight,
Reversed rev,
ResidualCapacity residual_capacity,
Pred pred,
Distance distance);
| Direction | Parameter | Description |
|---|---|---|
IN |
|
A directed graph. The graph’s type must be a model of Vertex List Graph and Incidence Graph. For each edge (u,v) in the graph, the reverse edge (v,u) must also be in the graph. |
IN |
|
The weight (also known as "length" or "cost") of each edge in the graph.
The |
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/OUT |
|
This maps edges to their residual capacity. 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. |
UTIL |
|
Used by the algorithm to store augmenting paths. The map must be a model of mutable Lvalue Property Map. The key type must be the graph’s vertex descriptor type and the value type must be the graph’s edge descriptor type. |
UTIL |
|
The shortest path weight from the source vertex to each vertex in the
graph |
(2) Named parameter version
template <typename Graph, typename P, typename T, typename R>
void cycle_canceling(
Graph& g,
const bgl_named_params<P, T, R>& params = all defaults);
| Direction | Parameter | Description |
|---|---|---|
IN |
|
A directed graph. The graph’s type must be a model of Vertex List Graph and Incidence Graph. For each edge (u,v) in the graph, the reverse edge (v,u) must also be in the graph. |
IN |
|
Named parameters passed via |
| Direction | Named Parameter | Description / Default |
|---|---|---|
IN/OUT |
|
This maps edges to their residual capacity. 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 |
|
The weight (also known as "length" or "cost") of each edge in the graph.
The |
UTIL |
|
Used by the algorithm to store augmenting paths. The map must be a model
of mutable Lvalue Property Map.
The key type must be the graph’s vertex descriptor type and the value type
must be the graph’s edge descriptor type. |
UTIL |
|
The shortest path weight from the source vertex to each vertex in the
graph |
IN |
|
Maps each vertex of the graph to a unique integer in the range
|
Description
The cycle_canceling() function calculates the minimum cost flow of a network
with given flow. See Section
Network Flow
Algorithms for a description of maximum flow. For given flow values f(u,v),
the function minimizes flow cost in such a way that for each v in V the
sum~u in V~ f(v,u) is preserved. Particularly if the input flow was the
maximum flow, the function produces min cost max flow.
The function 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 WeightMap
has to map each edge from ET to -weight of its reversed edge. Note that
edges from E can have negative weights.
If weights in the graph are nonnegative, the
successive_shortest_path_nonnegative_weights()
might be a better choice for min cost max flow.
The algorithm is described in Network Flows.
In each round the algorithm augments the negative cycle (in terms of weight) in the residual graph. If there is no negative cycle in the network, the cost is optimized.
Note that, although we mention capacity in the problem description, the actual algorithm doesn’t have to know it.
In order to find the cost of the result flow use:
find_flow_cost().