Find minimum st cut in a flow network (original) (raw)

Last Updated : 23 Jul, 2025

In a flow network, an s-t cut is a cut that requires the source 's' and the sink 't' to be in different subsets, and it consists of edges going from the source's side to the sink's side. The capacity of an s-t cut is defined by the sum of the capacity of each edge in the cut-set. (Source: Wiki) The problem discussed here is to find the minimum capacity s-t cut of the given network. The expected output is all edges of the minimum cut. For example, in the following flow network, example s-t cuts are {{0,1}, {0, 2}}, {{0, 2}, {1, 2}, {1, 3}}, etc. The minimum s-t cut is {{1, 3}, {4, 3}, {4 5}} which has capacity as 12+7+4 = 23.

We strongly recommend reading the below post first. Ford-Fulkerson Algorithm for Maximum Flow Problem

Minimum Cut and Maximum Flow:

Like Maximum Bipartite Matching, this is another problem that can be solved using Ford-Fulkerson Algorithm. This is based on the max-flow min-cut theorem.

The max-flow min-cut theorem states that in a flow network, the amount of maximum flow is equal to the capacity of the minimum cut.

From Ford-Fulkerson, we get a capacity of minimum cut. How to print all edges that form the minimum cut? The idea is to use a residual graph.

Following are steps to print all edges of the minimum cut.

  1. Run the Ford-Fulkerson algorithm and consider the final residual graph.
  2. Find the set of vertices that are reachable from the source in the residual graph.
  3. All edges which are from a reachable vertex to a non-reachable vertex are minimum cut edges. Print all such edges.

Following is the implementation of the above approach.

Try It Yourselfredirect icon

C++ `

// C++ program for finding minimum cut using Ford-Fulkerson #include #include <limits.h> #include <string.h> #include using namespace std;

// Number of vertices in given graph #define V 6

/* Returns true if there is a path from source 's' to sink 't' in residual graph. Also fills parent[] to store the path */ int bfs(int rGraph[V][V], int s, int t, int parent[]) { // Create a visited array and mark all vertices as not visited bool visited[V]; memset(visited, 0, sizeof(visited));

// Create a queue, enqueue source vertex and mark source vertex
// as visited
queue <int> q;
q.push(s);
visited[s] = true;
parent[s] = -1;

// Standard BFS Loop
while (!q.empty())
{
    int u = q.front();
    q.pop();

    for (int v=0; v<V; v++)
    {
        if (visited[v]==false && rGraph[u][v] > 0)
        {
            q.push(v);
            parent[v] = u;
            visited[v] = true;
        }
    }
}

// If we reached sink in BFS starting from source, then return
// true, else false
return (visited[t] == true);

}

// A DFS based function to find all reachable vertices from s. The function // marks visited[i] as true if i is reachable from s. The initial values in // visited[] must be false. We can also use BFS to find reachable vertices void dfs(int rGraph[V][V], int s, bool visited[]) { visited[s] = true; for (int i = 0; i < V; i++) if (rGraph[s][i] && !visited[i]) dfs(rGraph, i, visited); }

// Prints the minimum s-t cut void minCut(int graph[V][V], int s, int t) { int u, v;

// Create a residual graph and fill the residual graph with
// given capacities in the original graph as residual capacities
// in residual graph
int rGraph[V][V]; // rGraph[i][j] indicates residual capacity of edge i-j
for (u = 0; u < V; u++)
    for (v = 0; v < V; v++)
         rGraph[u][v] = graph[u][v];

int parent[V];  // This array is filled by BFS and to store path

// Augment the flow while there is a path from source to sink
while (bfs(rGraph, s, t, parent))
{
    // Find minimum residual capacity of the edges along the
    // path filled by BFS. Or we can say find the maximum flow
    // through the path found.
    int path_flow = INT_MAX;
    for (v=t; v!=s; v=parent[v])
    {
        u = parent[v];
        path_flow = min(path_flow, rGraph[u][v]);
    }

    // update residual capacities of the edges and reverse edges
    // along the path
    for (v=t; v != s; v=parent[v])
    {
        u = parent[v];
        rGraph[u][v] -= path_flow;
        rGraph[v][u] += path_flow;
    }
}

// Flow is maximum now, find vertices reachable from s
bool visited[V];
memset(visited, false, sizeof(visited));
dfs(rGraph, s, visited);

// Print all edges that are from a reachable vertex to
// non-reachable vertex in the original graph
for (int i = 0; i < V; i++)
  for (int j = 0; j < V; j++)
     if (visited[i] && !visited[j] && graph[i][j])
          cout << i << " - " << j << endl;

return;

}

// Driver program to test above functions int main() { // Let us create a graph shown in the above example int graph[V][V] = { {0, 16, 13, 0, 0, 0}, {0, 0, 10, 12, 0, 0}, {0, 4, 0, 0, 14, 0}, {0, 0, 9, 0, 0, 20}, {0, 0, 0, 7, 0, 4}, {0, 0, 0, 0, 0, 0} };

minCut(graph, 0, 5);

return 0;

}

Java

// Java program for finding min-cut in the given graph import java.util.LinkedList; import java.util.Queue;

public class Graph {

// Returns true if there is a path
// from source 's' to sink 't' in residual 
// graph. Also fills parent[] to store the path 
private static boolean bfs(int[][] rGraph, int s,
                            int t, int[] parent) {
    
    // Create a visited array and mark 
    // all vertices as not visited     
    boolean[] visited = new boolean[rGraph.length];
    
    // Create a queue, enqueue source vertex
    // and mark source vertex as visited     
    Queue<Integer> q = new LinkedList<Integer>();
    q.add(s);
    visited[s] = true;
    parent[s] = -1;
    
    // Standard BFS Loop     
    while (!q.isEmpty()) {
        int v = q.poll();
        for (int i = 0; i < rGraph.length; i++) {
            if (rGraph[v][i] > 0 && !visited[i]) {
                q.offer(i);
                visited[i] = true;
                parent[i] = v;
            }
        }
    }
    
    // If we reached sink in BFS starting 
    // from source, then return true, else false     
    return (visited[t] == true);
}

// A DFS based function to find all reachable 
// vertices from s. The function marks visited[i] 
// as true if i is reachable from s. The initial 
// values in visited[] must be false. We can also 
// use BFS to find reachable vertices
private static void dfs(int[][] rGraph, int s,
                            boolean[] visited) {
    visited[s] = true;
    for (int i = 0; i < rGraph.length; i++) {
            if (rGraph[s][i] > 0 && !visited[i]) {
                dfs(rGraph, i, visited);
            }
    }
}

// Prints the minimum s-t cut
private static void minCut(int[][] graph, int s, int t) {
    int u,v;
    
    // Create a residual graph and fill the residual 
    // graph with given capacities in the original 
    // graph as residual capacities in residual graph
    // rGraph[i][j] indicates residual capacity of edge i-j
    int[][] rGraph = new int[graph.length][graph.length]; 
    for (int i = 0; i < graph.length; i++) {
        for (int j = 0; j < graph.length; j++) {
            rGraph[i][j] = graph[i][j];
        }
    }

    // This array is filled by BFS and to store path
    int[] parent = new int[graph.length]; 
    
    // Augment the flow while there is path from source to sink     
    while (bfs(rGraph, s, t, parent)) {
        
        // Find minimum residual capacity of the edges 
        // along the path filled by BFS. Or we can say 
        // find the maximum flow through the path found.
        int pathFlow = Integer.MAX_VALUE;         
        for (v = t; v != s; v = parent[v]) {
            u = parent[v];
            pathFlow = Math.min(pathFlow, rGraph[u][v]);
        }
        
        // update residual capacities of the edges and 
        // reverse edges along the path
        for (v = t; v != s; v = parent[v]) {
            u = parent[v];
            rGraph[u][v] = rGraph[u][v] - pathFlow;
            rGraph[v][u] = rGraph[v][u] + pathFlow;
        }
    }
    
    // Flow is maximum now, find vertices reachable from s     
    boolean[] isVisited = new boolean[graph.length];     
    dfs(rGraph, s, isVisited);
    
    // Print all edges that are from a reachable vertex to
    // non-reachable vertex in the original graph     
    for (int i = 0; i < graph.length; i++) {
        for (int j = 0; j < graph.length; j++) {
            if (graph[i][j] > 0 && isVisited[i] && !isVisited[j]) {
                System.out.println(i + " - " + j);
            }
        }
    }
}

//Driver Program
public static void main(String args[]) {
    
    // Let us create a graph shown in the above example
    int graph[][] = { {0, 16, 13, 0, 0, 0},
            {0, 0, 10, 12, 0, 0},
            {0, 4, 0, 0, 14, 0},
            {0, 0, 9, 0, 0, 20},
            {0, 0, 0, 7, 0, 4},
            {0, 0, 0, 0, 0, 0}
        };
    minCut(graph, 0, 5);
}

} // This code is contributed by Himanshu Shekhar

Python

Python program for finding min-cut in the given graph

Complexity : (E*(V^3))

Total augmenting path = VE and BFS

with adj matrix takes :V^2 times

from collections import defaultdict

This class represents a directed graph

using adjacency matrix representation

class Graph:

def __init__(self,graph): 
    self.graph = graph # residual graph 
    self.org_graph = [i[:] for i in graph] 
    self. ROW = len(graph) 
    self.COL = len(graph[0]) 


'''Returns true if there is a path from 
source 's' to sink 't' in 
residual graph. Also fills 
parent[] to store the path '''
def BFS(self,s, t, parent): 

    # Mark all the vertices as not visited 
    visited =[False]*(self.ROW) 

    # Create a queue for BFS 
    queue=[] 

    # Mark the source node as visited and enqueue it 
    queue.append(s) 
    visited[s] = True

    # Standard BFS Loop 
    while queue: 

        #Dequeue a vertex from queue and print it 
        u = queue.pop(0) 

        # Get all adjacent vertices of 
        # the dequeued vertex u 
        # If a adjacent has not been
        # visited, then mark it 
        # visited and enqueue it 
        for ind, val in enumerate(self.graph[u]): 
            if visited[ind] == False and val > 0 : 
                queue.append(ind) 
                visited[ind] = True
                parent[ind] = u 

    # If we reached sink in BFS starting
    # from source, then return 
    # true, else false 
    return True if visited[t] else False
    
# Function for Depth first search 
# Traversal of the graph
def dfs(self, graph,s,visited):
    visited[s]=True
    for i in range(len(graph)):
        if graph[s][i]>0 and not visited[i]:
            self.dfs(graph,i,visited)

# Returns the min-cut of the given graph 
def minCut(self, source, sink): 

    # This array is filled by BFS and to store path 
    parent = [-1]*(self.ROW) 

    max_flow = 0 # There is no flow initially 

    # Augment the flow while there is path from source to sink 
    while self.BFS(source, sink, parent) : 

        # Find minimum residual capacity of the edges along the 
        # path filled by BFS. Or we can say find the maximum flow 
        # through the path found. 
        path_flow = float("Inf") 
        s = sink 
        while(s != source): 
            path_flow = min (path_flow, self.graph[parent[s]][s]) 
            s = parent[s] 

        # Add path flow to overall flow 
        max_flow += path_flow 

        # update residual capacities of the edges and reverse edges 
        # along the path 
        v = sink 
        while(v != source): 
            u = parent[v] 
            self.graph[u][v] -= path_flow 
            self.graph[v][u] += path_flow 
            v = parent[v] 

    visited=len(self.graph)*[False]
    self.dfs(self.graph,s,visited)

    # print the edges which initially had weights 
    # but now have 0 weight 
    for i in range(self.ROW): 
        for j in range(self.COL): 
            if self.graph[i][j] == 0 and\
            self.org_graph[i][j] > 0 and visited[i]: 
                print str(i) + " - " + str(j) 

Create a graph given in the above diagram

graph = [[0, 16, 13, 0, 0, 0], [0, 0, 10, 12, 0, 0], [0, 4, 0, 0, 14, 0], [0, 0, 9, 0, 0, 20], [0, 0, 0, 7, 0, 4], [0, 0, 0, 0, 0, 0]]

g = Graph(graph)

source = 0; sink = 5

g.minCut(source, sink)

This code is contributed by Neelam Yadav

C#

// C# program for finding min-cut in the given graph using System; using System.Collections.Generic;

class Graph {

// Returns true if there is a path
// from source 's' to sink 't' in residual 
// graph. Also fills parent[] to store the path 
private static bool bfs(int[,] rGraph, int s,
                        int t, int[] parent) 
{
    
    // Create a visited array and mark 
    // all vertices as not visited     
    bool[] visited = new bool[rGraph.Length];
    
    // Create a queue, enqueue source vertex
    // and mark source vertex as visited     
    Queue<int> q = new Queue<int>();
    q.Enqueue(s);
    visited[s] = true;
    parent[s] = -1;
    
    // Standard BFS Loop     
    while (q.Count != 0) 
    {
        int v = q.Dequeue();
        for (int i = 0; i < rGraph.GetLength(0); i++) 
        {
            if (rGraph[v,i] > 0 && !visited[i]) 
            {
                q.Enqueue(i);
                visited[i] = true;
                parent[i] = v;
            }
        }
    }
    
    // If we reached sink in BFS starting 
    // from source, then return true, else false     
    return (visited[t] == true);
}

// A DFS based function to find all reachable 
// vertices from s. The function marks visited[i] 
// as true if i is reachable from s. The initial 
// values in visited[] must be false. We can also 
// use BFS to find reachable vertices
private static void dfs(int[,] rGraph, int s,
                        bool[] visited) 
{
    visited[s] = true;
    for (int i = 0; i < rGraph.GetLength(0); i++) 
    {
        if (rGraph[s,i] > 0 && !visited[i])
        {
            dfs(rGraph, i, visited);
        }
    }
}

// Prints the minimum s-t cut
private static void minCut(int[,] graph, int s, int t) 
{
    int u, v;
    
    // Create a residual graph and fill the residual 
    // graph with given capacities in the original 
    // graph as residual capacities in residual graph
    // rGraph[i,j] indicates residual capacity of edge i-j
    int[,] rGraph = new int[graph.Length,graph.Length]; 
    for (int i = 0; i < graph.GetLength(0); i++)
    {
        for (int j = 0; j < graph.GetLength(1); j++)
        {
            rGraph[i, j] = graph[i, j];
        }
    }

    // This array is filled by BFS and to store path
    int[] parent = new int[graph.Length]; 
    
    // Augment the flow while there is path
    // from source to sink     
    while (bfs(rGraph, s, t, parent)) 
    {
        
        // Find minimum residual capacity of the edges 
        // along the path filled by BFS. Or we can say 
        // find the maximum flow through the path found.
        int pathFlow = int.MaxValue;         
        for (v = t; v != s; v = parent[v]) 
        {
            u = parent[v];
            pathFlow = Math.Min(pathFlow, rGraph[u, v]);
        }
        
        // update residual capacities of the edges and 
        // reverse edges along the path
        for (v = t; v != s; v = parent[v])
        {
            u = parent[v];
            rGraph[u, v] = rGraph[u, v] - pathFlow;
            rGraph[v, u] = rGraph[v, u] + pathFlow;
        } 
    }
    
    // Flow is maximum now, find vertices reachable from s     
    bool[] isVisited = new bool[graph.Length];     
    dfs(rGraph, s, isVisited);
    
    // Print all edges that are from a reachable vertex to
    // non-reachable vertex in the original graph     
    for (int i = 0; i < graph.GetLength(0); i++) 
    {
        for (int j = 0; j < graph.GetLength(1); j++)
        {
            if (graph[i, j] > 0 && 
                isVisited[i] && !isVisited[j])
            {
                Console.WriteLine(i + " - " + j);
            }
        }
    }
}

// Driver Code
public static void Main(String []args)
{
    
    // Let us create a graph shown 
    // in the above example
    int [,]graph = {{0, 16, 13, 0, 0, 0},
                    {0, 0, 10, 12, 0, 0},
                    {0, 4, 0, 0, 14, 0},
                    {0, 0, 9, 0, 0, 20},
                    {0, 0, 0, 7, 0, 4},
                    {0, 0, 0, 0, 0, 0}};
    minCut(graph, 0, 5);
}

}

// This code is contributed by PrinciRaj1992

JavaScript

// JavaScript program for finding min-cut in the given graph

// Returns true if there is a path
// from source 's' to sink 't' in residual
// graph. Also fills parent[] to store the path
function bfs(rGraph, s, t, parent){
    // Create a visited array and mark
    // all vertices as not visited
    var visited = new Array(rGraph.length).fill(false);
    
    // Create a queue, enqueue source vertex
    // and mark source vertex as visited
    let q = [];
    q.push(s);
    visited[s] = true;
    parent[s] = -1;
    
    // Standard BFS Loop
    while(q.length){
        var v = q.shift();
        for (let i = 0; i < rGraph.length; i++) {
            if (rGraph[v][i] > 0 && !visited[i]) {
                q.push(i);
                visited[i] = true;
                parent[i] = v;
            }
        }
    }
    
    // If we reached sink in BFS starting
    // from source, then return true, else false    
    return (visited[t] == true);
}

// A DFS based function to find all reachable
// vertices from s. The function marks visited[i]
// as true if i is reachable from s. The initial
// values in visited[] must be false. We can also
// use BFS to find reachable vertices
function dfs(rGraph, s, visited){
    visited[s] = true;
    
    for (let i = 0; i < rGraph.length; i++) {
        if (rGraph[s][i] > 0 && !visited[i]) {
            dfs(rGraph, i, visited);
        }
    }
}

// Prints the minimum s-t cut
function minCut(graph, s, t){
    var u;
    var v;
    
    // Create a residual graph and fill the residual
    // graph with given capacities in the original
    // graph as residual capacities in residual graph
    // rGraph[i][j] indicates residual capacity of edge i-j
    var rGraph = new Array(graph.length);
    for(let i=0;i<graph.length;i++){
        rGraph[i] = new Array(graph.length);
        for(let j=0;j<graph.length;j++){
            rGraph[i][j] = graph[i][j];
        }
    }
    
    // This array is filled by BFS and to store path
    var parent = new Array(graph.length);
    
    // Augment the flow while there is path from source to sink
    while(bfs(rGraph, s, t, parent)){
        // Find minimum residual capacity of the edges
        // along the path filled by BFS. Or we can say
        // find the maximum flow through the path found.
        var pathFlow = Number.MAX_VALUE;
        for (v = t; v != s; v = parent[v]) {
            u = parent[v];
            pathFlow = Math.min(pathFlow, rGraph[u][v]);
        }
        
        // update residual capacities of the edges and
        // reverse edges along the path
        for (v = t; v != s; v = parent[v]) {
            u = parent[v];
            rGraph[u][v] = rGraph[u][v] - pathFlow;
            rGraph[v][u] = rGraph[v][u] + pathFlow;
        }
    }
    
    // Flow is maximum now, find vertices reachable from s
    var isVisited = new Array(graph.length).fill(false);
    dfs(rGraph, s, isVisited);
    
    // Print all edges that are from a reachable vertex to
    // non-reachable vertex in the original graph 
    for (let i = 0; i < graph.length; i++) {
        for (let j = 0; j < graph.length; j++) {
            if (graph[i][j] > 0 && isVisited[i] && !isVisited[j]) {
                console.log(i + " - " + j + "<br>");
            }
        }
    }
}

// Let us create a graph shown in the above example
var graph = [ [0, 16, 13, 0, 0, 0],
              [0, 0, 10, 12, 0, 0],
              [0, 4, 0, 0, 14, 0],
              [0, 0, 9, 0, 0, 20],
              [0, 0, 0, 7, 0, 4],
              [0, 0, 0, 0, 0, 0] ];
              
minCut(graph, 0, 5);

// This code is contributed by lokeshmvs21.

`

Time Complexity: O(V.(E)2)

Space Complexity: O(V2)