Given a directed graph and two vertices in it, source 's' and destination 't', find out the maximum number of edge disjoint paths from s to t. Two paths are said edge disjoint if they don't share any edge.

There can be maximum two edge disjoint paths from source 0 to destination 7 in the above graph. Two edge disjoint paths are highlighted below in red and blue colors are 0-2-6-7 and 0-3-6-5-7.

Note that the paths may be different, but the maximum number is same. For example, in the above diagram, another possible set of paths is 0-1-2-6-7 and 0-3-6-5-7 respectively.
This problem can be solved by reducing it to maximum flow problem. Following are steps.
- Consider the given source and destination as source and sink in flow network. Assign unit capacity to each edge.
- Run Ford-Fulkerson algorithm to find the maximum flow from source to sink.
- The maximum flow is equal to the maximum number of edge-disjoint paths.
When we run Ford-Fulkerson, we reduce the capacity by a unit. Therefore, the edge can not be used again. So the maximum flow is equal to the maximum number of edge-disjoint paths.
Following is the implementation of the above algorithm. Most of the code is taken from here.
// C++ program to find maximum number of edge disjoint paths
#include <iostream>
#include <limits.h>
#include <string.h>
#include <queue>
using namespace std;
// Number of vertices in given graph
#define V 8
/* Returns true if there is a path from source 's' to sink 't' in
residual graph. Also fills parent[] to store the path */
bool 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);
}
// Returns the maximum number of edge-disjoint paths from s to t.
// This function is copy of forFulkerson() discussed at https://www.geeksforgeeks.org/dsa/ford-fulkerson-algorithm-for-maximum-flow-problem/
int findDisjointPaths(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]; // Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if there
// is an edge. If rGraph[i][j] is 0, then there is not)
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
int max_flow = 0; // There is no flow initially
// 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 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;
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow (max_flow is equal to maximum
// number of edge-disjoint paths)
return max_flow;
}
// Driver program to test above functions
int main()
{
// Let us create a graph shown in the above example
int graph[V][V] = { {0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 1, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0}
};
int s = 0;
int t = 7;
cout << "There can be maximum " << findDisjointPaths(graph, s, t)
<< " edge-disjoint paths from " << s <<" to "<< t ;
return 0;
}
// Java program to find maximum number
// of edge disjoint paths
import java.util.*;
class GFG
{
// Number of vertices in given graph
static int V = 8;
/* Returns true if there is a path from
source 's' to sink 't' in residual graph.
Also fills parent[] to store the path */
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[V];
// Create a queue, enqueue source vertex and
// mark source vertex as visited
Queue <Integer> q = new LinkedList<>();
q.add(s);
visited[s] = true;
parent[s] = -1;
// Standard BFS Loop
while (!q.isEmpty())
{
int u = q.peek();
q.remove();
for (int v = 0; v < V; v++)
{
if (visited[v] == false &&
rGraph[u][v] > 0)
{
q.add(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);
}
// Returns the maximum number of edge-disjoint
// paths from s to t. This function is copy of
// forFulkerson() discussed at https://www.geeksforgeeks.org/dsa/ford-fulkerson-algorithm-for-maximum-flow-problem/
static int findDisjointPaths(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
// Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if there
// is an edge. If rGraph[i][j] is 0, then there is not)
int [][]rGraph = new int[V][V];
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];
// This array is filled by BFS and to store path
int []parent = new int[V];
int max_flow = 0; // There is no flow initially
// 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 path_flow = Integer.MAX_VALUE;
for (v = t; v != s; v = parent[v])
{
u = parent[v];
path_flow = Math.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;
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow (max_flow is equal to
// maximum number of edge-disjoint paths)
return max_flow;
}
// Driver Code
public static void main(String[] args)
{
// Let us create a graph shown in the above example
int graph[][] = {{0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 1, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0}};
int s = 0;
int t = 7;
System.out.println("There can be maximum " +
findDisjointPaths(graph, s, t) +
" edge-disjoint paths from " +
s + " to "+ t);
}
}
// This code is contributed by PrinciRaj1992
# Python program to find maximum number of edge disjoint paths
# 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. ROW = len(graph)
'''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
# Returns the maximum number of edge-disjoint paths from
#s to t in the given graph
def findDisjointPaths(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]
return max_flow
# Create a graph given in the above diagram
graph = [[0, 1, 1, 1, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 0, 1, 0, 0, 0, 0, 1],
[0, 1, 0, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0]]
g = Graph(graph)
source = 0; sink = 7
print ("There can be maximum %d edge-disjoint paths from %d to %d" %
(g.findDisjointPaths(source, sink), source, sink))
# This code is contributed by Neelam Yadav
// C# program to find maximum number
// of edge disjoint paths
using System;
using System.Collections.Generic;
class GFG
{
// Number of vertices in given graph
static int V = 8;
/* Returns true if there is a path from
source 's' to sink 't' in residual graph.
Also fills parent[] to store the path */
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[V];
// 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 u = q.Peek();
q.Dequeue();
for (int v = 0; v < V; v++)
{
if (visited[v] == false &&
rGraph[u, v] > 0)
{
q.Enqueue(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);
}
// Returns the maximum number of edge-disjoint
// paths from s to t. This function is copy of
// forFulkerson() discussed at https://www.geeksforgeeks.org/dsa/ford-fulkerson-algorithm-for-maximum-flow-problem/
static int findDisjointPaths(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
// Residual graph where rGraph[i,j] indicates
// residual capacity of edge from i to j (if there
// is an edge. If rGraph[i,j] is 0, then there is not)
int [,]rGraph = new int[V, V];
for (u = 0; u < V; u++)
for (v = 0; v < V; v++)
rGraph[u, v] = graph[u, v];
// This array is filled by BFS and
// to store path
int []parent = new int[V];
int max_flow = 0; // There is no flow initially
// 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 path_flow = int.MaxValue;
for (v = t; v != s; v = parent[v])
{
u = parent[v];
path_flow = Math.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;
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow (max_flow is equal to
// maximum number of edge-disjoint paths)
return max_flow;
}
// Driver Code
public static void Main(String[] args)
{
// Let us create a graph shown
// in the above example
int [,]graph = {{0, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 1, 0, 0, 0, 0, 0},
{0, 0, 0, 1, 0, 0, 1, 0},
{0, 0, 0, 0, 0, 0, 1, 0},
{0, 0, 1, 0, 0, 0, 0, 1},
{0, 1, 0, 0, 0, 0, 0, 1},
{0, 0, 0, 0, 0, 1, 0, 1},
{0, 0, 0, 0, 0, 0, 0, 0}};
int s = 0;
int t = 7;
Console.WriteLine("There can be maximum " +
findDisjointPaths(graph, s, t) +
" edge-disjoint paths from " +
s + " to "+ t);
}
}
// This code is contributed by Rajput-Ji
<script>
// Javascript program to find maximum number
// of edge disjoint paths
// Number of vertices in given graph
let V = 8;
/* 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
let visited = new Array(V);
for(let i = 0; i < V; i++)
visited[i] = 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 != 0)
{
let u = q[0];
q.shift();
for(let 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);
}
// Returns the maximum number of edge-disjoint
// paths from s to t. This function is copy of
// forFulkerson() discussed at https://www.geeksforgeeks.org/dsa/ford-fulkerson-algorithm-for-maximum-flow-problem/
function findDisjointPaths(graph, s, t)
{
let u, v;
// Create a residual graph and fill the
// residual graph with given capacities
// in the original graph as residual capacities
// in residual graph
// Residual graph where rGraph[i][j] indicates
// residual capacity of edge from i to j (if
// there is an edge. If rGraph[i][j] is 0,
// then there is not)
let rGraph = new Array(V);
for(u = 0; u < V; u++)
{
rGraph[u] = new Array(V);
for(v = 0; v < V; v++)
rGraph[u][v] = graph[u][v];
}
// This array is filled by BFS and to store path
let parent = new Array(V);
// There is no flow initially
let max_flow = 0;
// 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.
let path_flow = Number.MAX_VALUE;
for(v = t; v != s; v = parent[v])
{
u = parent[v];
path_flow = Math.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;
}
// Add path flow to overall flow
max_flow += path_flow;
}
// Return the overall flow (max_flow is equal
// to maximum number of edge-disjoint paths)
return max_flow;
}
// Driver Code
let graph = [ [ 0, 1, 1, 1, 0, 0, 0, 0 ],
[ 0, 0, 1, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 1, 0, 0, 1, 0 ],
[ 0, 0, 0, 0, 0, 0, 1, 0 ],
[ 0, 0, 1, 0, 0, 0, 0, 1 ],
[ 0, 1, 0, 0, 0, 0, 0, 1 ],
[ 0, 0, 0, 0, 0, 1, 0, 1 ],
[ 0, 0, 0, 0, 0, 0, 0, 0 ] ];
let s = 0;
let t = 7;
document.write("There can be maximum " +
findDisjointPaths(graph, s, t) +
" edge-disjoint paths from " +
s + " to " + t + "<br>");
// This code is contributed by avanitrachhadiya2155
</script>
Output
There can be maximum 2 edge-disjoint paths from 0 to 7
Time Complexity : O(|V| * E2) ,where E is the number of edges and V is the number of vertices.
Space Complexity :O(V) ,as we created queue.
Time Complexity: Same as time complexity of Edmonds-Karp implementation of Ford-Fulkerson (See time complexity discussed here)