Open In App

Find minimum s-t cut in a flow network

Last Updated : 03 May, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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. 

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 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.


Output

1 - 3
4 - 3
4 - 5

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

Space Complexity: O(V2)



Previous Article
Next Article

Similar Reads

Cut all the rods with some length such that the sum of cut-off length is maximized
Given N rods of different lengths. The task is to cut all the rods with some maximum integer height 'h' such that the sum of cut-off lengths of the rod is maximized and must be greater than M. Print -1 if no such cut is possible. Note: A rod cannot be cut also. Examples: Input: N = 7, M = 8, a[] = {1, 2, 3, 5, 4, 7, 6} Output: 3 Rod 1 and 2 are unt
9 min read
Cuts and Network Flow
The backbone analysis of any network is broadly accomplished by using Graph Theory and its Algorithms. The performance constraints are Reliability, Delay/Throughput and the goal is to minimize cost. In the backbone designing of a network the concerned points and considerations are : What should be the backbone topology ?Assignment of Line Capacitie
4 min read
Java Program to Find Minimum Number of Edges to Cut to Make the Graph Disconnected
Given a connected graph, the task is to find the minimum number of edges to cut/remove to make the given graph disconnected. A graph is disconnected if there exists at least two vertices of the graph that are not connected by a path. Examples: Input: Output: Minimum Number of Edges to Remove = 2 Approach: The approach to this problem is to find the
4 min read
Analysis and applications Karger’s algorithm for Minimum Cut
We have introduced and discussed below Karger's algorithm in set 1. 1) Initialize contracted graph CG as copy of original graph 2) While there are more than 2 vertices. a) Pick a random edge (u, v) in the contracted graph. b) Merge (or contract) u and v into a single vertex (update the contracted graph). c) Remove self-loops 3) Return cut represent
4 min read
Minimum squares to evenly cut a rectangle
Given a rectangular sheet of length l and width w. we need to divide this sheet into square sheets such that the number of square sheets should be as minimum as possible.Examples: Input :l= 4 w=6 Output :6 We can form squares with side of 1 unit, But the number of squares will be 24, this is not minimum. If we make square with side of 2, then we ha
4 min read
Minimum Cost to cut a board into squares
A board of length m and width n is given, we need to break this board into m*n squares such that cost of breaking is minimum. cutting cost for each edge will be given for the board. In short, we need to choose such a sequence of cutting such that cost is minimized. Examples: For above board optimal way to cut into square is: Total minimum cost in a
8 min read
Paper Cut into Minimum Number of Squares
Given a paper of size, A x B. Task is to cut the paper into squares of any size. Find the minimum number of squares that can be cut from the paper. Examples: Input : 13 x 29Output : 9Explanation : 2 (squares of size 13x13) + 4 (squares of size 3x3) + 3 (squares of size 1x1)=9Input : 4 x 5Output : 5Explanation : 1 (squares of size 4x4) + 4 (squares
11 min read
Paper Cut into Minimum Number of Squares | Set 2
Given a paper of size A x B. Task is to cut the paper into squares of any size. Find the minimum number of squares that can be cut from the paper. Examples: Input : 36 x 30 Output : 5 Explanation : 3 (squares of size 12x12) + 2 (squares of size 18x18) Input : 4 x 5 Output : 5 Explanation : 1 (squares of size 4x4) + 4 (squares of size 1x1) Asked in
10 min read
Introduction and implementation of Karger's algorithm for Minimum Cut
Given an undirected and unweighted graph, find the smallest cut (smallest number of edges that disconnects the graph into two components). The input graph may have parallel edges. For example consider the following example, the smallest cut has 2 edges. A Simple Solution use Max-Flow based s-t cut algorithm to find minimum cut. Consider every pair
15+ min read
Minimum Cost Maximum Flow from a Graph using Bellman Ford Algorithm
Given a source node S, a sink node T, two matrices Cap[ ][ ] and Cost[ ][ ] representing a graph, where Cap[i][j] is the capacity of a directed edge from node i to node j and cost[i][j] is the cost of sending one unit of flow along a directed edge from node i to node j, the task is to find a flow with the minimum-cost maximum-flow possible from the
15+ min read
Article Tags :
Practice Tags :