diff --git a/doc/weights.xml b/doc/weights.xml
index 22c6b71e9..b69369a12 100644
--- a/doc/weights.xml
+++ b/doc/weights.xml
@@ -272,6 +272,34 @@ gap> Sum(flow[1]);
<#/GAPDoc>
+<#GAPDoc Label="DigraphMinimumCut">
+
+
+ A list of lists of integers.
+
+ If digraph is an edge-weighted digraph with distinct vertices s and
+ t, this returns a list of two lists representing the components of
+ a minimal s-t cut of digraph.
+
+ An s-t cut is a partition of the vertices \{ S, T \} such that s is in S and
+ t is in T. The capacity of an s-t cut is the sum of the weights of every
+ edge whose source is in S and whose range is in T. A minimum s-t cut is an s-t
+ cut whose capacity is minimal.
+
+ This attribute is computed by using and the
+ max-cut min-flow theorem.
+
+ See .
+ g := EdgeWeightedDigraph([[2, 2], [3], []], [[3, 2], [1], []]);
+
+gap> DigraphMinimumCut(g, 1, 3);
+[ [ 2, 1 ], [3]]
+]]>
+
+
+<#/GAPDoc>
+
<#GAPDoc Label="RandomUniqueEdgeWeightedDigraph">
diff --git a/doc/z-chap5.xml b/doc/z-chap5.xml
index 759876e11..64454c8d0 100644
--- a/doc/z-chap5.xml
+++ b/doc/z-chap5.xml
@@ -32,6 +32,7 @@
<#Include Label="EdgeWeightedDigraphShortestPaths">
<#Include Label="EdgeWeightedDigraphShortestPath">
<#Include Label="DigraphMaximumFlow">
+ <#Include Label="DigraphMinimumCut">
<#Include Label="RandomUniqueEdgeWeightedDigraph">
diff --git a/gap/weights.gd b/gap/weights.gd
index 7d11bf5f7..6930da8da 100644
--- a/gap/weights.gd
+++ b/gap/weights.gd
@@ -35,9 +35,11 @@ DeclareGlobalFunction("DIGRAPHS_Edge_Weighted_FloydWarshall");
DeclareGlobalFunction("DIGRAPHS_Edge_Weighted_Bellman_Ford");
DeclareGlobalFunction("DIGRAPHS_Edge_Weighted_Dijkstra");
-# 5. Maximum Flow
+# 5. Maximum Flow and Minimum Cut
DeclareOperation("DigraphMaximumFlow",
[IsDigraph and HasEdgeWeights, IsPosInt, IsPosInt]);
+DeclareOperation("DigraphMinimumCut",
+ [IsDigraph and HasEdgeWeights, IsPosInt, IsPosInt]);
# 6. Random edge weighted digraphs
DeclareOperation("RandomUniqueEdgeWeightedDigraph", [IsPosInt]);
diff --git a/gap/weights.gi b/gap/weights.gi
index 5b246b002..8c2838e9b 100644
--- a/gap/weights.gi
+++ b/gap/weights.gi
@@ -638,7 +638,7 @@ function(D, source)
end);
#############################################################################
-# 5. Maximum Flow
+# 5. Maximum Flow and Minimum Cut
#############################################################################
InstallMethod(DigraphMaximumFlow, "for an edge weighted digraph",
@@ -772,6 +772,52 @@ function(D, start, destination)
return flows;
end);
+InstallMethod(DigraphMinimumCut, "for an edge weighted digraph",
+[IsDigraph and HasEdgeWeights, IsPosInt, IsPosInt],
+function(D, s, t)
+ local weights, outs, vertices, flow, residuals, u, v, S, T, Q;
+
+ # Extract important data
+ weights := EdgeWeights(D);
+ outs := OutNeighbours(D);
+ vertices := DigraphVertices(D);
+
+ # Check input
+ if s < 1 or s > Length(vertices) then
+ ErrorNoReturn(" must be a vertex of ,");
+ elif t < 1 or t > Length(vertices) then
+ ErrorNoReturn(" must be a vertex of ,");
+ elif s = t then
+ ErrorNoReturn(" and must be distinct");
+ fi;
+
+ # Find the residual edge capacities under the maximum flow
+ flow := DigraphMaximumFlow(D, s, t);
+ residuals := weights - flow;
+
+ # Carry out a BFS to find all the vertices in the residual
+ # network which are reachable from s. This gives the minimum
+ # cut by the max-flow min-cut theorem.
+
+ S := [s];
+ Q := [s];
+ while not IsEmpty(Q) do
+ u := Q[1];
+ Remove(Q, 1);
+ for v in [1 .. Length(outs[u])] do
+ if residuals[u][v] > 0 then
+ if not outs[u][v] in S then
+ Add(Q, outs[u][v]);
+ Add(S, outs[u][v]);
+ fi;
+ fi;
+ od;
+ od;
+
+ T := Difference(vertices, S);
+ return [S, T];
+end);
+
#############################################################################
# 6. Random edge weighted digraphs
#############################################################################
diff --git a/tst/standard/weights.tst b/tst/standard/weights.tst
index 59a632140..3e1a20bc1 100644
--- a/tst/standard/weights.tst
+++ b/tst/standard/weights.tst
@@ -291,7 +291,7 @@ gap> EdgeWeightedDigraphShortestPath(d, 1, 3);
[ [ 1, 2, 3 ], [ 1, 1 ] ]
#############################################################################
-# 5. Maximum Flow
+# 5. Maximum Flow and Minimum Cut
#############################################################################
# Maximum flow: empty digraphs
@@ -368,6 +368,80 @@ gap> gr := EdgeWeightedDigraph([[2], [3, 6], [4], [1, 6], [1, 3], []],
gap> DigraphMaximumFlow(gr, 5, 6);
[ [ 10 ], [ 3, 7 ], [ 7 ], [ 0, 7 ], [ 10, 4 ], [ ] ]
+# Minimum cut: empty digraphs
+gap> d := EdgeWeightedDigraph([], []);
+
+gap> DigraphMinimumCut(d, 1, 1);
+Error, must be a vertex of ,
+
+# Minimum cut: single vertex (also empty digraphs)
+gap> d := EdgeWeightedDigraph([[]], [[]]);
+
+gap> DigraphMinimumCut(d, 1, 1);
+Error, and must be distinct
+
+# Minimum cut: source = dest
+gap> d := EdgeWeightedDigraph([[2], []], [[5], []]);
+
+gap> DigraphMinimumCut(d, 1, 1);
+Error, and must be distinct
+
+# Minimum cut: has loop
+gap> d := EdgeWeightedDigraph([[1, 2], []], [[5, 10], []]);
+
+gap> DigraphMinimumCut(d, 1, 2);
+[ [ 1 ], [ 2 ] ]
+
+# Minimum cut: invalid source
+gap> d := EdgeWeightedDigraph([[1, 2], []], [[5, 10], []]);
+
+gap> DigraphMinimumCut(d, 5, 2);
+Error, must be a vertex of ,
+
+# Minimum cut: invalid sink
+gap> d := EdgeWeightedDigraph([[1, 2], []], [[5, 10], []]);
+
+gap> DigraphMinimumCut(d, 1, 5);
+Error, must be a vertex of ,
+
+# Minimum cut: sink not reachable
+gap> d := EdgeWeightedDigraph([[1], []], [[5], []]);
+
+gap> DigraphMinimumCut(d, 1, 2);
+[ [ 1 ], [ 2 ] ]
+
+# Minimum cut: source has in neighbours
+gap> d := EdgeWeightedDigraph([[2], [3], []], [[5], [10], []]);
+
+gap> DigraphMinimumCut(d, 2, 3);
+[ [ 2 ], [ 1, 3 ] ]
+
+# Minimum cut: sink has out-neighbours
+gap> d := EdgeWeightedDigraph([[2], [3], [2]], [[5], [10], [7]]);
+
+gap> DigraphMinimumCut(d, 2, 3);
+[ [ 2 ], [ 1, 3 ] ]
+
+# Minimum cut: cycle
+gap> d := EdgeWeightedDigraph([[2], [3], [1]], [[5], [10], [7]]);
+
+gap> DigraphMinimumCut(d, 1, 3);
+[ [ 1 ], [ 2, 3 ] ]
+
+# Minimum cut: example from Wikipedia
+gap> gr := EdgeWeightedDigraph([[3, 4], [], [2, 4], [2]],
+> [[10, 5], [], [5, 15], [10]]);;
+gap> DigraphMinimumCut(gr, 1, 2);
+[ [ 1 ], [ 2, 3, 4 ] ]
+gap> DigraphMinimumCut(gr, 3, 2);
+[ [ 4, 3 ], [ 1, 2 ] ]
+
+# Minimum cut: example from Wikipedia article on Push-label maximum flow
+gap> gr := EdgeWeightedDigraph([[2], [3, 6], [4], [1, 6], [1, 3], []],
+> [[12], [3, 7], [10], [5, 10], [15, 4], []]);;
+gap> DigraphMinimumCut(gr, 5, 6);
+[ [ 1, 2, 5 ], [ 3, 4, 6 ] ]
+
#############################################################################
# 6. Random edge-weighted digraphs
#############################################################################