Count all possible Paths between two Vertices
Last Updated :
28 Sep, 2023
Count the total number of ways or paths that exist between two vertices in a directed graph. These paths don’t contain a cycle, the simple enough reason is that a cycle contains an infinite number of paths and hence they create a problem
Examples:
For the following Graph:
Input: Count paths between A and E
Output: Total paths between A and E are 4
Explanation: The 4 paths between A and E are:
A -> E
A -> B -> E
A -> C -> E
A -> B -> D -> C -> E
Input: Count paths between A and C
Output: Total paths between A and C are 2
Explanation: The 2 paths between A and C are:
A -> C
A -> B -> D -> C
Count paths between two vertices using Backtracking:
To solve the problem follow the below idea:
The problem can be solved using backtracking, which says to take a path and start walking on it and check if it leads us to the destination vertex then count the path and backtrack to take another path. If the path doesn’t lead to the destination vertex, discard the path. This type of graph traversal is called Backtracking.
Backtracking for the above graph can be shown like this:
Note: The red color vertex is the source vertex and the light-blue color vertex is destination, rest are either intermediate or discarded paths.
This give four paths between source(A) and destination(E) vertex
Why this solution will not work for a graph which contains cycles?
The Problem Associated with this is that now if one more edge is added between C and B, it would make a cycle (B -> D -> C -> B). And hence after every cycle through the loop, the length path will increase and that will be considered a different path, and there would be infinitely many paths because of the cycle
Follow the given steps to solve the problem:
- Create a recursive function that takes the index of a node of a graph and the destination index. Keep a global or a static variable count to store the count.
- Keep a record of the nodes visited using a visited array and while returning mark the current node to be unvisited to discover other paths.
- If the current node is the destination then increase the count.
- Else for all the adjacent nodes, i.e. nodes that are accessible from the current node, call the recursive function with the index of the adjacent node and the destination.
- Print the Count as the required answer.
Below is the implementation of the above approach.
C++
#include <bits/stdc++.h>
using namespace std;
class Graph {
public :
Graph( int vertices);
void add_edge( int src, int dst);
int count_paths( int src, int dst, int vertices);
private :
int m_vertices;
list< int >* m_neighbours;
void path_counter( int src, int dst, int & path_count,
vector< bool >& visited);
};
Graph::Graph( int vertices)
{
m_vertices = vertices;
m_neighbours = new list< int >[vertices];
}
void Graph::add_edge( int src, int dst)
{
m_neighbours[src].push_back(dst);
}
int Graph::count_paths( int src, int dst, int vertices)
{
int path_count = 0;
vector< bool > visited(vertices, false );
path_counter(src, dst, path_count, visited);
return path_count;
}
void Graph::path_counter( int src, int dst, int & path_count,
vector< bool >& visited)
{
visited[src] = true ;
if (src == dst) {
path_count++;
}
else {
for ( auto neighbour : m_neighbours[src]) {
if (!visited[neighbour])
path_counter(neighbour, dst, path_count,
visited);
}
}
visited[src] = false ;
}
int main()
{
Graph g(5);
g.add_edge(0, 1);
g.add_edge(0, 2);
g.add_edge(0, 4);
g.add_edge(1, 3);
g.add_edge(1, 4);
g.add_edge(2, 3);
g.add_edge(2, 1);
g.add_edge(3, 2);
cout << g.count_paths(0, 4, 5);
return 0;
}
|
Java
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
class Graph {
private int V;
private LinkedList<Integer> adj[];
@SuppressWarnings ( "unchecked" ) Graph( int v)
{
V = v;
adj = new LinkedList[v];
for ( int i = 0 ; i < v; ++i)
adj[i] = new LinkedList<>();
}
void addEdge( int v, int w)
{
adj[v].add(w);
}
int countPathsUtil( int u, int d, int pathCount)
{
if (u == d) {
pathCount++;
}
else {
Iterator<Integer> i = adj[u].listIterator();
while (i.hasNext()) {
int n = i.next();
pathCount = countPathsUtil(n, d, pathCount);
}
}
return pathCount;
}
int countPaths( int s, int d)
{
int pathCount = 0 ;
pathCount = countPathsUtil(s, d, pathCount);
return pathCount;
}
public static void main(String args[])
{
Graph g = new Graph( 5 );
g.addEdge( 0 , 1 );
g.addEdge( 0 , 2 );
g.addEdge( 0 , 3 );
g.addEdge( 1 , 3 );
g.addEdge( 2 , 3 );
g.addEdge( 1 , 4 );
g.addEdge( 2 , 4 );
int s = 0 , d = 3 ;
System.out.println(g.countPaths(s, d));
}
}
|
Python3
class Graph:
def __init__( self , V):
self .V = V
self .adj = [[] for i in range (V)]
def addEdge( self , u, v):
self .adj[u].append(v)
def countPaths( self , s, d):
visited = [ False ] * self .V
pathCount = [ 0 ]
self .countPathsUtil(s, d, visited, pathCount)
return pathCount[ 0 ]
def countPathsUtil( self , u, d,
visited, pathCount):
visited[u] = True
if (u = = d):
pathCount[ 0 ] + = 1
else :
i = 0
while i < len ( self .adj[u]):
if ( not visited[ self .adj[u][i]]):
self .countPathsUtil( self .adj[u][i], d,
visited, pathCount)
i + = 1
visited[u] = False
if __name__ = = '__main__' :
g = Graph( 4 )
g.addEdge( 0 , 1 )
g.addEdge( 0 , 2 )
g.addEdge( 0 , 3 )
g.addEdge( 2 , 0 )
g.addEdge( 2 , 1 )
g.addEdge( 1 , 3 )
s = 2
d = 3
print (g.countPaths(s, d))
|
C#
using System;
using System.Collections.Generic;
public class Graph {
private List< int >[] adj;
Graph( int v)
{
adj = new List< int >[ v ];
for ( int i = 0; i < v; ++i)
adj[i] = new List< int >();
}
void addEdge( int v, int w)
{
adj[v].Add(w);
}
int countPathsUtil( int u, int d, int pathCount)
{
if (u == d) {
pathCount++;
}
else {
foreach ( int i in adj[u])
{
int n = i;
pathCount = countPathsUtil(n, d, pathCount);
}
}
return pathCount;
}
int countPaths( int s, int d)
{
int pathCount = 0;
pathCount = countPathsUtil(s, d, pathCount);
return pathCount;
}
public static void Main(String[] args)
{
Graph g = new Graph(5);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(0, 3);
g.addEdge(1, 3);
g.addEdge(2, 3);
g.addEdge(1, 4);
g.addEdge(2, 4);
int s = 0, d = 3;
Console.WriteLine(g.countPaths(s, d));
}
}
|
Javascript
<script>
let V;
let adj;
function Graph(v)
{
V = v;
adj = new Array(v);
for (let i = 0; i < v; ++i)
adj[i] = [];
}
function addEdge(v,w)
{
adj[v].push(w);
}
function countPathsUtil(u,d,pathCount)
{
if (u == d) {
pathCount++;
}
else {
for (let i=0;i<adj[u].length;i++) {
let n = adj[u][i];
pathCount = countPathsUtil(n, d, pathCount);
}
}
return pathCount;
}
function countPaths(s,d)
{
let pathCount = 0;
pathCount = countPathsUtil(s, d,
pathCount);
return pathCount;
}
Graph(5);
addEdge(0, 1);
addEdge(0, 2);
addEdge(0, 3);
addEdge(1, 3);
addEdge(2, 3);
addEdge(1, 4);
addEdge(2, 4);
let s = 0, d = 3;
document.write(countPaths(s, d));
</script>
|
Time Complexity: O(2^n), where n is the number of vertices in the graph. This is because in the worst case scenario, the program will have to recursively visit all possible paths from the source to the destination, which can be exponential in the number of vertices.
Auxiliary Space: O(N), Auxiliary stack space used by recursion calls
Please Login to comment...