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 http://goo.gl/wtQ4Ks 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 http://goo.gl/wtQ4Ks 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 http://goo.gl/wtQ4Ks 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 http://goo.gl/wtQ4Ks 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> |
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)