
- DSA - Home
- DSA - Overview
- DSA - Environment Setup
- DSA - Algorithms Basics
- DSA - Asymptotic Analysis
- Data Structures
- DSA - Data Structure Basics
- DSA - Data Structures and Types
- DSA - Array Data Structure
- DSA - Skip List Data Structure
- Linked Lists
- DSA - Linked List Data Structure
- DSA - Doubly Linked List Data Structure
- DSA - Circular Linked List Data Structure
- Stack & Queue
- DSA - Stack Data Structure
- DSA - Expression Parsing
- DSA - Queue Data Structure
- DSA - Circular Queue Data Structure
- DSA - Priority Queue Data Structure
- DSA - Deque Data Structure
- Searching Algorithms
- DSA - Searching Algorithms
- DSA - Linear Search Algorithm
- DSA - Binary Search Algorithm
- DSA - Interpolation Search
- DSA - Jump Search Algorithm
- DSA - Exponential Search
- DSA - Fibonacci Search
- DSA - Sublist Search
- DSA - Hash Table
- Sorting Algorithms
- DSA - Sorting Algorithms
- DSA - Bubble Sort Algorithm
- DSA - Insertion Sort Algorithm
- DSA - Selection Sort Algorithm
- DSA - Merge Sort Algorithm
- DSA - Shell Sort Algorithm
- DSA - Heap Sort Algorithm
- DSA - Bucket Sort Algorithm
- DSA - Counting Sort Algorithm
- DSA - Radix Sort Algorithm
- DSA - Quick Sort Algorithm
- Matrices Data Structure
- DSA - Matrices Data Structure
- DSA - Lup Decomposition In Matrices
- DSA - Lu Decomposition In Matrices
- Graph Data Structure
- DSA - Graph Data Structure
- DSA - Depth First Traversal
- DSA - Breadth First Traversal
- DSA - Spanning Tree
- DSA - Topological Sorting
- DSA - Strongly Connected Components
- DSA - Biconnected Components
- DSA - Augmenting Path
- DSA - Network Flow Problems
- DSA - Flow Networks In Data Structures
- DSA - Edmonds Blossom Algorithm
- DSA - Maxflow Mincut Theorem
- Tree Data Structure
- DSA - Tree Data Structure
- DSA - Tree Traversal
- DSA - Binary Search Tree
- DSA - AVL Tree
- DSA - Red Black Trees
- DSA - B Trees
- DSA - B+ Trees
- DSA - Splay Trees
- DSA - Range Queries
- DSA - Segment Trees
- DSA - Fenwick Tree
- DSA - Fusion Tree
- DSA - Hashed Array Tree
- DSA - K-Ary Tree
- DSA - Kd Trees
- DSA - Priority Search Tree Data Structure
- Recursion
- DSA - Recursion Algorithms
- DSA - Tower of Hanoi Using Recursion
- DSA - Fibonacci Series Using Recursion
- Divide and Conquer
- DSA - Divide and Conquer
- DSA - Max-Min Problem
- DSA - Strassen's Matrix Multiplication
- DSA - Karatsuba Algorithm
- Greedy Algorithms
- DSA - Greedy Algorithms
- DSA - Travelling Salesman Problem (Greedy Approach)
- DSA - Prim's Minimal Spanning Tree
- DSA - Kruskal's Minimal Spanning Tree
- DSA - Dijkstra's Shortest Path Algorithm
- DSA - Map Colouring Algorithm
- DSA - Fractional Knapsack Problem
- DSA - Job Sequencing with Deadline
- DSA - Optimal Merge Pattern Algorithm
- Dynamic Programming
- DSA - Dynamic Programming
- DSA - Matrix Chain Multiplication
- DSA - Floyd Warshall Algorithm
- DSA - 0-1 Knapsack Problem
- DSA - Longest Common Sub-sequence Algorithm
- DSA - Travelling Salesman Problem (Dynamic Approach)
- Hashing
- DSA - Hashing Data Structure
- DSA - Collision In Hashing
- Disjoint Set
- DSA - Disjoint Set
- DSA - Path Compression And Union By Rank
- Heap
- DSA - Heap Data Structure
- DSA - Binary Heap
- DSA - Binomial Heap
- DSA - Fibonacci Heap
- Tries Data Structure
- DSA - Tries
- DSA - Standard Tries
- DSA - Compressed Tries
- DSA - Suffix Tries
- Treaps
- DSA - Treaps Data Structure
- Bit Mask
- DSA - Bit Mask In Data Structures
- Bloom Filter
- DSA - Bloom Filter Data Structure
- Approximation Algorithms
- DSA - Approximation Algorithms
- DSA - Vertex Cover Algorithm
- DSA - Set Cover Problem
- DSA - Travelling Salesman Problem (Approximation Approach)
- Randomized Algorithms
- DSA - Randomized Algorithms
- DSA - Randomized Quick Sort Algorithm
- DSA - Karger’s Minimum Cut Algorithm
- DSA - Fisher-Yates Shuffle Algorithm
- Miscellaneous
- DSA - Infix to Postfix
- DSA - Bellmon Ford Shortest Path
- DSA - Maximum Bipartite Matching
- DSA Useful Resources
- DSA - Questions and Answers
- DSA - Selection Sort Interview Questions
- DSA - Merge Sort Interview Questions
- DSA - Insertion Sort Interview Questions
- DSA - Heap Sort Interview Questions
- DSA - Bubble Sort Interview Questions
- DSA - Bucket Sort Interview Questions
- DSA - Radix Sort Interview Questions
- DSA - Cycle Sort Interview Questions
- DSA - Quick Guide
- DSA - Useful Resources
- DSA - Discussion
Maxflow Mincut Theorem
Let's talk about Maxflow and Mincut. These are like two sides of the same coin when dealing with network flow problems. If you ever wondered how stuff moves through a network, whether its water in pipes, cars on roads, or data in a network, then youre already thinking in terms of max flow and min cut.
What is Maxflow?
Maxflow (Maximum Flow) is all about figuring out the most stuff (data, water, traffic) that can move from one point (source) to another (sink) in a network without breaking any capacity limits. Imagine a bunch of pipes carrying water, and you want to know the maximum amount of water that can flow through the system without overflowing.
What is Mincut?
Mincut (Minimum Cut) is kind of the opposite. Its about finding the weakest link in the network that, if cut, would completely stop the flow from the source to the sink. Think of it like identifying the narrowest point in a road system where a traffic jam would completely block all movement.
Maxflow and Mincut Theorem
Heres something cool: The Maxflow-Mincut Theorem says that the maximum flow in a network is equal to the total capacity of the smallest set of edges that, if removed, would stop the flow completely. This means if you
These concepts arent just theoretical; they are used in real life all the time:
- Traffic Management: Figuring out the best way to manage congestion in roads.
- Computer Networks: Making sure data packets travel efficiently.
- Airline Scheduling: Ensuring flights are assigned to routes in the best way possible.
- Water Distribution: Managing water flow in pipelines to avoid shortages.
- Project Management: Finding the critical path in workflows to improve efficiency.
Example to Understand Maxflow
Imagine a city with roads connecting different areas. If you want to get the max number of cars from the start point to the endpoint, thats maxflow. Now, let's write code.
Maxflow using Ford-Fulkerson Algorithm
Steps to find the maxflow in a graph using the Ford-Fulkerson Algorithm:
1. Start with the initial flow as 0. 2. While there is an augmenting path from source to sink: a. Find the path with the minimum capacity. b. Increase the flow along the path. 3. The maximum flow is the sum of all flows along the augmenting paths.
Here's the code to find the maxflow in a graph using the Ford-Fulkerson Algorithm:
#include <stdio.h> #include <string.h> #include <limits.h> #define V 6 // Number of vertices // Function to perform DFS and find an augmenting path int dfs(int rGraph[V][V], int s, int t, int parent[]) { int visited[V]; memset(visited, 0, sizeof(visited)); int stack[V], top = -1; stack[++top] = s; visited[s] = 1; while (top >= 0) { int u = stack[top--]; for (int v = 0; v < V; v++) { if (!visited[v] && rGraph[u][v] > 0) { stack[++top] = v; visited[v] = 1; parent[v] = u; if (v == t) { return 1; } } } } return 0; } // Ford-Fulkerson algorithm to find the max-flow int fordFulkerson(int graph[V][V], int source, int sink) { int rGraph[V][V]; // Residual graph for (int i = 0; i < V; i++) { for (int j = 0; j < V; j++) { rGraph[i][j] = graph[i][j]; } } int parent[V]; int maxFlow = 0; // Augment the flow while there is an augmenting path while (dfs(rGraph, source, sink, parent)) { int pathFlow = INT_MAX; for (int v = sink; v != source; v = parent[v]) { int u = parent[v]; pathFlow = (pathFlow < rGraph[u][v]) ? pathFlow : rGraph[u][v]; } maxFlow += pathFlow; // Update the residual graph for (int v = sink; v != source; v = parent[v]) { int u = parent[v]; rGraph[u][v] -= pathFlow; rGraph[v][u] += pathFlow; } } return maxFlow; } int main() { // Example graph 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} }; int source = 0, sink = 5; printf("Maximum flow: %d\n", fordFulkerson(graph, source, sink)); return 0; }
Output
Following is the output of the above code:
Maximum flow: 23
#include <iostream> #include <climits> #define V 6 // Number of vertices using namespace std; // Function to perform DFS and find an augmenting path bool dfs(int rGraph[V][V], int s, int t, int parent[]) { bool visited[V] = {0}; int stack[V], top = -1; stack[++top] = s; visited[s] = true; while (top >= 0) { int u = stack[top--]; for (int v = 0; v < V; v++) { if (!visited[v] && rGraph[u][v] > 0) { stack[++top] = v; visited[v] = true; parent[v] = u; if (v == t) return true; } } } return false; } // Ford-Fulkerson algorithm to find the max-flow int fordFulkerson(int graph[V][V], int source, int sink) { int rGraph[V][V]; // Residual graph for (int i = 0; i < V; i++) { for (int j = 0; j < V; j++) { rGraph[i][j] = graph[i][j]; } } int parent[V]; int maxFlow = 0; // Augment the flow while there is an augmenting path while (dfs(rGraph, source, sink, parent)) { int pathFlow = INT_MAX; for (int v = sink; v != source; v = parent[v]) { int u = parent[v]; pathFlow = (pathFlow < rGraph[u][v]) ? pathFlow : rGraph[u][v]; } maxFlow += pathFlow; // Update the residual graph for (int v = sink; v != source; v = parent[v]) { int u = parent[v]; rGraph[u][v] -= pathFlow; rGraph[v][u] += pathFlow; } } return maxFlow; } int main() { // Example graph 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} }; int source = 0, sink = 5; cout << "Maximum flow: " << fordFulkerson(graph, source, sink) << endl; return 0; }
Output
Following is the output of the above code:
Maximum flow: 23
import java.util.*; public class Maxflow { static final int V = 6; // Number of vertices // Function to perform DFS and find an augmenting path static boolean dfs(int rGraph[][], int s, int t, int parent[]) { boolean visited[] = new boolean[V]; Stack<Integer> stack = new Stack<>(); stack.push(s); visited[s] = true; while (!stack.isEmpty()) { int u = stack.pop(); for (int v = 0; v < V; v++) { if (!visited[v] && rGraph[u][v] > 0) { stack.push(v); visited[v] = true; parent[v] = u; if (v == t) return true; } } } return false; } // Ford-Fulkerson algorithm to find the max-flow static int fordFulkerson(int graph[][], int source, int sink) { int rGraph[][] = new int[V][V]; // Residual graph for (int i = 0; i < V; i++) { for (int j = 0; j < V; j++) { rGraph[i][j] = graph[i][j]; } } int parent[] = new int[V]; int maxFlow = 0; // Augment the flow while there is an augmenting path while (dfs(rGraph, source, sink, parent)) { int pathFlow = Integer.MAX_VALUE; for (int v = sink; v != source; v = parent[v]) { int u = parent[v]; pathFlow = Math.min(pathFlow, rGraph[u][v]); } maxFlow += pathFlow; // Update the residual graph for (int v = sink; v != source; v = parent[v]) { int u = parent[v]; rGraph[u][v] -= pathFlow; rGraph[v][u] += pathFlow; } } return maxFlow; } public static void main(String[] args) { // Example graph 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} }; int source = 0, sink = 5; System.out.println("Maximum flow: " + fordFulkerson(graph, source, sink)); } }
Output
Following is the output of the above code:
Maximum flow: 23
V = 6 # Number of vertices # Function to perform DFS and find an augmenting path def dfs(rGraph, s, t, parent): visited = [False] * V stack = [] stack.append(s) visited[s] = True while stack: u = stack.pop() for v in range(V): if not visited[v] and rGraph[u][v] > 0: stack.append(v) visited[v] = True parent[v] = u if v == t: return True return False # Ford-Fulkerson algorithm to find the max-flow def fordFulkerson(graph, source, sink): rGraph = [[0] * V for _ in range(V)] # Residual graph for i in range(V): for j in range(V): rGraph[i][j] = graph[i][j] parent = [-1] * V maxFlow = 0 # Augment the flow while there is an augmenting path while dfs(rGraph, source, sink, parent): pathFlow = float('inf') v = sink while v != source: u = parent[v] pathFlow = min(pathFlow, rGraph[u][v]) v = parent[v] maxFlow += pathFlow # Update the residual graph v = sink while v != source: u = parent[v] rGraph[u][v] -= pathFlow rGraph[v][u] += pathFlow v = parent[v] return maxFlow # Example graph 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]] source, sink = 0, 5 print("Maximum flow:", fordFulkerson(graph, source, sink))
Output
Following is the output of the above code:
Maximum flow: 23
Example to Understand Mincut
We already know what mincut is, let's code to find the mincut in a graph using the Ford-Fulkerson Algorithm:
Mincut using Ford-Fulkerson Algorithm
Steps to find the mincut in a graph using the Ford-Fulkerson Algorithm:
Initialize the graph and residual graph, and set up the parent[] array to track paths. Perform BFS to find an augmenting path from source to sink in the residual graph. Update residual graph by reducing the flow along the found path and adding reverse flow. Repeat BFS until no augmenting path is found. Perform DFS to find all reachable vertices from the source in the residual graph. Print the edges that go from a reachable vertex to a non-reachable vertex, which form the minimum cut.
Now, let's see how to find the mincut in a graph using the Ford-Fulkerson Algorithm:
#include <stdio.h> #include <string.h> #include <limits.h> #include <stdbool.h> #define V 6 // Simple queue structure for BFS typedef struct { int items[V]; int front, rear; } Queue; void initQueue(Queue* q) { q->front = -1; q->rear = -1; } int isEmpty(Queue* q) { return q->front == -1; } void enqueue(Queue* q, int value) { if (q->rear == V - 1) return; // Queue overflow if (q->front == -1) q->front = 0; q->items[++(q->rear)] = value; } int dequeue(Queue* q) { if (isEmpty(q)) return -1; // Queue underflow int item = q->items[q->front]; if (q->front == q->rear) q->front = q->rear = -1; else q->front++; return item; } int bfs(int rGraph[V][V], int s, int t, int parent[]) { bool visited[V]; memset(visited, 0, sizeof(visited)); Queue q; initQueue(&q); enqueue(&q, s); visited[s] = 1; parent[s] = -1; while (!isEmpty(&q)) { int u = dequeue(&q); for (int v = 0; v < V; v++) { if (!visited[v] && rGraph[u][v] > 0) { enqueue(&q, v); parent[v] = u; visited[v] = 1; } } } return (visited[t] == 1); } void dfs(int rGraph[V][V], int s, bool visited[]) { visited[s] = 1; for (int i = 0; i < V; i++) { if (rGraph[s][i] && !visited[i]) dfs(rGraph, i, visited); } } void minCut(int graph[V][V], int s, int t) { int u, v; int rGraph[V][V]; for (u = 0; u < V; u++) { for (v = 0; v < V; v++) { rGraph[u][v] = graph[u][v]; } } int parent[V]; while (bfs(rGraph, s, t, parent)) { int path_flow = INT_MAX; for (v = t; v != s; v = parent[v]) { u = parent[v]; path_flow = (path_flow < rGraph[u][v]) ? path_flow : rGraph[u][v]; } for (v = t; v != s; v = parent[v]) { u = parent[v]; rGraph[u][v] -= path_flow; rGraph[v][u] += path_flow; } } bool visited[V]; memset(visited, 0, sizeof(visited)); dfs(rGraph, s, visited); for (int i = 0; i < V; i++) { for (int j = 0; j < V; j++) { if (visited[i] && !visited[j] && graph[i][j]) { printf("%d - %d\n", i, j); } } } } int main() { int graph[V][V] = { {0, 10, 0, 10, 0, 0}, {0, 0, 5, 0, 0, 0}, {0, 0, 0, 0, 10, 0}, {0, 0, 0, 0, 0, 20}, {0, 0, 0, 0, 0, 10}, {0, 0, 0, 0, 0, 0} }; printf("Minimum Cut Edges: \n"); minCut(graph, 0, 5); return 0; }
Output
Following is the output of the above code:
Minimum Cut Edges: 0 - 3 1 - 2
#include <iostream> #include <limits.h> #include <cstring> #include <queue> using namespace std; // Define the number of vertices in the graph #define NUM_VERTICES 6 // Helper function to perform BFS and check if there's a path from source to sink // It also updates the parent array with the path bool bfs(int residualGraph[NUM_VERTICES][NUM_VERTICES], int source, int sink, int parent[]) { // Array to track visited vertices bool visited[NUM_VERTICES]; memset(visited, false, sizeof(visited)); // Queue for BFS traversal, starting with the source queue<int> q; q.push(source); visited[source] = true; parent[source] = -1; // Perform BFS while (!q.empty()) { int node = q.front(); q.pop(); // Explore all adjacent nodes for (int adj = 0; adj < NUM_VERTICES; adj++) { if (!visited[adj] && residualGraph[node][adj] > 0) { q.push(adj); parent[adj] = node; visited[adj] = true; } } } // Return true if the sink is reachable return (visited[sink] == true); } // Recursive DFS to find all reachable vertices from the source void dfs(int residualGraph[NUM_VERTICES][NUM_VERTICES], int source, bool visited[]) { visited[source] = true; for (int i = 0; i < NUM_VERTICES; i++) { if (residualGraph[source][i] && !visited[i]) { dfs(residualGraph, i, visited); } } } // Function to compute and print the minimum cut void findMinCut(int originalGraph[NUM_VERTICES][NUM_VERTICES], int source, int sink) { int u, v; // Initialize the residual graph int residualGraph[NUM_VERTICES][NUM_VERTICES]; for (u = 0; u < NUM_VERTICES; u++) { for (v = 0; v < NUM_VERTICES; v++) { residualGraph[u][v] = originalGraph[u][v]; } } // Array to store the path from source to sink int parent[NUM_VERTICES]; // Augment the flow while there is a path from source to sink while (bfs(residualGraph, source, sink, parent)) { // Find the minimum capacity along the path int pathFlow = INT_MAX; for (v = sink; v != source; v = parent[v]) { u = parent[v]; pathFlow = min(pathFlow, residualGraph[u][v]); } // Update the residual graph capacities for (v = sink; v != source; v = parent[v]) { u = parent[v]; residualGraph[u][v] -= pathFlow; residualGraph[v][u] += pathFlow; } } // At this point, the maximum flow is found. Now find the reachable vertices bool visited[NUM_VERTICES]; memset(visited, false, sizeof(visited)); dfs(residualGraph, source, visited); // Print all edges that are from reachable to non-reachable vertices in the original graph cout << "Minimum Cut Edges: \n"; for (int i = 0; i < NUM_VERTICES; i++) { for (int j = 0; j < NUM_VERTICES; j++) { if (visited[i] && !visited[j] && originalGraph[i][j]) { cout << i << " - " << j << endl; } } } } int main() { // Example graph int graph[NUM_VERTICES][NUM_VERTICES] = { {0, 10, 0, 10, 0, 0}, {0, 0, 5, 0, 0, 0}, {0, 0, 0, 0, 10, 0}, {0, 0, 0, 0, 0, 20}, {0, 0, 0, 0, 0, 10}, {0, 0, 0, 0, 0, 0} }; // Find the minimum cut between source (0) and sink (5) findMinCut(graph, 0, 5); return 0; }
Output
Following is the output of the above code:
Minimum Cut Edges: 0 - 3 1 - 2
import java.util.*; public class MinCut { static final int V = 6; // Function to perform BFS and find if there's a path from source to sink static boolean bfs(int rGraph[][], int s, int t, int parent[]) { boolean visited[] = new boolean[V]; Arrays.fill(visited, false); Queue<Integer> q = new LinkedList<>(); q.add(s); visited[s] = true; parent[s] = -1; while (!q.isEmpty()) { int u = q.poll(); for (int v = 0; v < V; v++) { if (!visited[v] && rGraph[u][v] > 0) { q.add(v); parent[v] = u; visited[v] = true; } } } return visited[t]; } // Function to perform DFS and mark all reachable vertices from source static void dfs(int rGraph[][], int s, boolean visited[]) { visited[s] = true; for (int i = 0; i < V; i++) { if (rGraph[s][i] > 0 && !visited[i]) { dfs(rGraph, i, visited); } } } // Function to print the minimum cut static void minCut(int graph[][], int s, int t) { int rGraph[][] = new int[V][V]; for (int i = 0; i < V; i++) { for (int j = 0; j < V; j++) { rGraph[i][j] = graph[i][j]; } } int parent[] = new int[V]; while (bfs(rGraph, s, t, parent)) { int pathFlow = Integer.MAX_VALUE; for (int v = t; v != s; v = parent[v]) { int u = parent[v]; pathFlow = Math.min(pathFlow, rGraph[u][v]); } for (int v = t; v != s; v = parent[v]) { int u = parent[v]; rGraph[u][v] -= pathFlow; rGraph[v][u] += pathFlow; } } boolean visited[] = new boolean[V]; Arrays.fill(visited, false); dfs(rGraph, s, visited); System.out.println("Minimum Cut Edges:"); for (int i = 0; i < V; i++) { for (int j = 0; j < V; j++) { if (visited[i] && !visited[j] && graph[i][j] > 0) { System.out.println(i + " - " + j); } } } } public static void main(String[] args) { int graph[][] = { {0, 10, 0, 10, 0, 0}, {0, 0, 5, 0, 0, 0}, {0, 0, 0, 0, 10, 0}, {0, 0, 0, 0, 0, 20}, {0, 0, 0, 0, 0, 10}, {0, 0, 0, 0, 0, 0} }; minCut(graph, 0, 5); } }
Output
Following is the output of the above code:
Minimum Cut Edges: 0 - 3 1 - 2
from collections import deque V = 6 # Function to perform BFS and find if there's a path from source to sink def bfs(rGraph, s, t, parent): visited = [False] * V q = deque([s]) visited[s] = True parent[s] = -1 while q: u = q.popleft() for v in range(V): if not visited[v] and rGraph[u][v] > 0: q.append(v) parent[v] = u visited[v] = True return visited[t] # Function to perform DFS and mark all reachable vertices from source def dfs(rGraph, s, visited): visited[s] = True for i in range(V): if rGraph[s][i] > 0 and not visited[i]: dfs(rGraph, i, visited) # Function to print the minimum cut def minCut(graph, s, t): rGraph = [row[:] for row in graph] parent = [-1] * V while bfs(rGraph, s, t, parent): pathFlow = float("inf") v = t while v != s: u = parent[v] pathFlow = min(pathFlow, rGraph[u][v]) v = parent[v] v = t while v != s: u = parent[v] rGraph[u][v] -= pathFlow rGraph[v][u] += pathFlow v = parent[v] visited = [False] * V dfs(rGraph, s, visited) print("Minimum Cut Edges:") for i in range(V): for j in range(V): if visited[i] and not visited[j] and graph[i][j] > 0: print(f"{i} - {j}") # Driver code graph = [ [0, 10, 0, 10, 0, 0], [0, 0, 5, 0, 0, 0], [0, 0, 0, 0, 10, 0], [0, 0, 0, 0, 0, 20], [0, 0, 0, 0, 0, 10], [0, 0, 0, 0, 0, 0] ] minCut(graph, 0, 5)
Output
Following is the output of the above code:
Minimum Cut Edges: 0 - 3 1 - 2
Conclusion
Maxflow helps us figure out how much we can push through a system, while Mincut tells us where the weakest spots are. Both are super useful in real-life applications, from networks to transportation and beyond. Learning these concepts can help solve big optimization problems in different fields.