Find minimum s-t cut in a flow network

21 Jun, 2022
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 minimum capacity s-t cut of the given network. 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 to read the below post first. Ford-Fulkerson Algorithm for Maximum Flow Problem
Minimum Cut and Maximum Flow:
Like Maximum Bipartite Matching, this is another problem which can solved using Ford-Fulkerson Algorithm. This is based on 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 capacity of the minimum cut. 
From Ford-Fulkerson, we get capacity of minimum cut. How to print all edges that form the minimum cut? The idea is to use residual graph. 
Following are steps to print all edges of the minimum cut.
Run Ford-Fulkerson algorithm and consider the final residual graph. Find the set of vertices that are reachable from the source in the residual graph. All edges which are from a reachable vertex to non-reachable vertex are minimum cut edges. Print all such edges. 
Run Ford-Fulkerson algorithm and consider the final residual graph. 
Find the set of vertices that are reachable from the source in the residual graph. 
All edges which are from a reachable vertex to non-reachable vertex are minimum cut edges. Print all such edges. 
Following is the implementation of the above approach. 
C++
Java
Python
C#
// C++ program for finding minimum cut using Ford-Fulkerson#include <iostream>#include <limits.h>#include <string.h>#include <queue>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 verticesvoid 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 cutvoid 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 edhes 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 functionsint 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 program for finding min-cut in the given graphimport 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 tere is path from source to sink            while (bfs(rGraph, s, t, parent)) {                         // Find minimum residual capacity of the edhes            // 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 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 representationclass 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 diagramgraph = [[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# program for finding min-cut in the given graphusing 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 edhes            // 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
1 - 3
4 - 3
4 - 5

princiraj1992
hardikkoriintern
Max-Flow
Graph
Graph
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Topological Sorting
Kruskal’s Minimum Spanning Tree Algorithm | Greedy Algo-2
Detect Cycle in a Directed Graph
Find if there is a path between two vertices in a directed graph
Introduction to Data Structures
Floyd Warshall Algorithm | DP-16
Disjoint Set (Or Union-Find) | Set 1 (Detect Cycle in an Undirected Graph)
What is Data Structure: Types, Classifications and Applications
Bellman–Ford Algorithm | DP-23
Travelling Salesman Problem | Set 1 (Naive and Dynamic Programming)