For a lecture on digraphs and network flows, I prepared the following capacitated directed network problem in order to explore its solution both manually via a maximum-flow/minimum-cut algorithm and computationally using the NetworkX library in Python:

The number on each arc represents the flow capacity of that arc and the vertices and
are the source and the sink for the flow respectively (all arcs containing
are directed away from
and all arcs containing
are directed towards
).
The max-flow/min-cut algorithm involves a labelling procedure which, starting from an initial flow (e.g., a zero flow) enables augmentation of flows along some arcs as well as reduction of flows along others. The idea is to increase the flow from to
as much as possible subject to the capacity constraints on the arcs by using the algorithm to keep finding flow-augmenting routes through the network. The process terminates when all flow-augmenting routes have been found and a maximum flow value for the network thus becomes known. The algorithm will also result in some of the arcs in the network becoming saturated, i.e., filled to capacity, and a set of arcs containing some of these saturated arcs will constitute a minimum cut for the network. Such a minimum cut is a set of arcs with the smallest possible sum of capacities such that removal of all the arcs in the set divides the network into two disjoint parts
and
, the part
containing the source
and the part
containing the sink
. A theorem known as the max-flow min-cut theorem states that the maximum flow value must equal the capacity value of the minimum cut for a basic network such as the one in the diagram above. Finding a minimum cut using the saturated arcs at the end of the algorithm thus provides a useful way to check that the final flow is indeed a maximal one.
Below, I will solve the above problem both manually and using the NetworkX library in Python. For the manual solution, I will use a labelling procedure to record movement from one vertex to the next vertex
with the notation
, where
is the size of flow that is possible along the arc subject to the capacity of the arc and also subject to the possible flow at the previous step. Where there is a choice of arc when moving from one vertex to the next, we choose alphabetically. When moving backwards along an arc, this is indicated with a minus sign so that, for example,
indicates that we moved from
to
along an arc that was actually directed from
to
.
The manual solution is a little burdensome mainly because it requires making repeated copies of the network showing the adjustments at each step of the algorithm. Below I will render these copies by hand. At each step, each arc is labelled with two numbers separated by a comma, the first number being the flow along the arc and the second being the capacity of the arc. I will highlight that an arc is saturated by thickening the line representing the arc. We assume a zero initial flow, represented as follows in a manual copy of the above network:

Starting from vertex , we choose alphabetically the arc
. The labels are:
. The path is
. The flow increase is
. The saturated arc is
. Making these amendments, the network looks as follows after this first run:

For the next run, we begin again with arc . The labels are:
. The path is
. The flow increase is
. The saturated arc is
. The network looks as follows after this second run:

We begin again with arc . The labels are:
. The path is
. The flow increase is
. The saturated arc is
. The network looks as follows after this third run:

We begin again with arc . The labels are:
. The path is
. The flow increase is
. The saturated arc is
. The network looks as follows after this fourth run:

We begin again with arc . The labels are:
. The path is
. The flow increase is
. The saturated arc is
. The network looks as follows after this fifth run:

Proceeding alphabetically, we now begin with arc . The labels are:
. The path is
. The flow increase is
. The saturated arcs are
and
. The network looks as follows after this sixth run:

We begin again with arc . The labels are:
. The path is
. The flow increase is
. The saturated arc is
. The network looks as follows after this seventh run:

We begin again with arc . The labels are:
. The path is
. The flow increase is
. The saturated arcs are
and
. The network looks as follows after this eighth run:

Proceeding alphabetically, we now begin with arc . The labels are:
. The path is
. The flow increase is
. The saturated arc is
. The network looks as follows after this ninth run:

We begin again with arc . The labels are:
. The path is
. The flow increase is
. The saturated arc is
. The network looks as follows after this tenth run:

The algorithm is now complete. The diagram below shows the maximum flow and a minimum cut for this network:

The maximum flow has the value . The minimum cut is the set of arcs
which has capacity
.
Having solved the problem manually, it is interesting to now compare this solution with a computational solution produced using the library NetworkX in Python. I did the coding for this problem in a Jupyter Notebook as follows:





