Find if there is a path between two vertices in a directed graph
Last Updated :
07 Feb, 2023
Given a Directed Graph and two vertices in it, check whether there is a path from the first given vertex to second.
Example:
Consider the following Graph:
Input : (u, v) = (1, 3)
Output: Yes
Explanation: There is a path from 1 to 3, 1 -> 2 -> 3
Input : (u, v) = (3, 6)
Output: No
Explanation: There is no path from 3 to 6
Approach: Either Breadth First Search (BFS) or Depth First Search (DFS) can be used to find path between two vertices. Take the first vertex as a source in BFS (or DFS), follow the standard BFS (or DFS). If the second vertex is found in our traversal, then return true else return false.
BFS Algorithm:
- The implementation below is using BFS.
- Create a queue and a visited array initially filled with 0, of size V where V is a number of vertices.
- Insert the starting node in the queue, i.e. push u in the queue and mark u as visited.
- Run a loop until the queue is not empty.
- Dequeue the front element of the queue. Iterate all its adjacent elements. If any of the adjacent elements is the destination return true. Push all the adjacent and unvisited vertices in the queue and mark them as visited.
- Return false as the destination is not reached in BFS.
Implementation: C++, Java, and Python codes that use BFS for finding the reachability of the second vertex from the first vertex.
C++
#include<iostream>
#include <list>
using namespace std;
class Graph
{
int V;
list< int > *adj;
public :
Graph( int V);
void addEdge( int v, int w);
bool isReachable( int s, int d);
};
Graph::Graph( int V)
{
this ->V = V;
adj = new list< int >[V];
}
void Graph::addEdge( int v, int w)
{
adj[v].push_back(w);
}
bool Graph::isReachable( int s, int d)
{
if (s == d)
return true ;
bool *visited = new bool [V];
for ( int i = 0; i < V; i++)
visited[i] = false ;
list< int > queue;
visited[s] = true ;
queue.push_back(s);
list< int >::iterator i;
while (!queue.empty())
{
s = queue.front();
queue.pop_front();
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (*i == d)
return true ;
if (!visited[*i])
{
visited[*i] = true ;
queue.push_back(*i);
}
}
}
return false ;
}
int main()
{
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
int u = 1, v = 3;
if (g.isReachable(u, v))
cout<< "\n There is a path from " << u << " to " << v;
else
cout<< "\n There is no path from " << u << " to " << v;
u = 3, v = 1;
if (g.isReachable(u, v))
cout<< "\n There is a path from " << u << " to " << v;
else
cout<< "\n There is no path from " << u << " to " << v;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
import java.util.LinkedList;
class Graph
{
private int V;
private LinkedList<Integer> adj[];
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); }
Boolean isReachable( int s, int d)
{
LinkedList<Integer>temp;
boolean visited[] = new boolean [V];
LinkedList<Integer> queue = new LinkedList<Integer>();
visited[s]= true ;
queue.add(s);
Iterator<Integer> i;
while (queue.size()!= 0 )
{
s = queue.poll();
int n;
i = adj[s].listIterator();
while (i.hasNext())
{
n = i.next();
if (n==d)
return true ;
if (!visited[n])
{
visited[n] = true ;
queue.add(n);
}
}
}
return false ;
}
public static void main(String args[])
{
Graph g = new Graph( 4 );
g.addEdge( 0 , 1 );
g.addEdge( 0 , 2 );
g.addEdge( 1 , 2 );
g.addEdge( 2 , 0 );
g.addEdge( 2 , 3 );
g.addEdge( 3 , 3 );
int u = 1 ;
int v = 3 ;
if (g.isReachable(u, v))
System.out.println( "There is a path from " + u + " to " + v);
else
System.out.println( "There is no path from " + u + " to " + v);;
u = 3 ;
v = 1 ;
if (g.isReachable(u, v))
System.out.println( "There is a path from " + u + " to " + v);
else
System.out.println( "There is no path from " + u + " to " + v);;
}
}
|
Python3
from collections import defaultdict
class Graph:
def __init__( self ,vertices):
self .V = vertices
self .graph = defaultdict( list )
def addEdge( self ,u,v):
self .graph[u].append(v)
def isReachable( self , s, d):
visited = [ False ] * ( self .V)
queue = []
queue.append(s)
visited[s] = True
while queue:
n = queue.pop( 0 )
if n = = d:
return True
for i in self .graph[n]:
if visited[i] = = False :
queue.append(i)
visited[i] = True
return False
g = Graph( 4 )
g.addEdge( 0 , 1 )
g.addEdge( 0 , 2 )
g.addEdge( 1 , 2 )
g.addEdge( 2 , 0 )
g.addEdge( 2 , 3 )
g.addEdge( 3 , 3 )
u = 1 ; v = 3
if g.isReachable(u, v):
print ( "There is a path from %d to %d" % (u,v))
else :
print ( "There is no path from %d to %d" % (u,v))
u = 3 ; v = 1
if g.isReachable(u, v) :
print ( "There is a path from %d to %d" % (u,v))
else :
print ( "There is no path from %d to %d" % (u,v))
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
class Graph
{
private int V;
private LinkedList< int >[] adj;
Graph( int v)
{
V = v;
adj = new LinkedList< int >[v];
for ( int i = 0; i < v; ++i)
adj[i] = new LinkedList< int >();
}
void addEdge( int v, int w)
{
adj[v].AddLast(w);
}
bool isReachable( int s, int d)
{
bool [] visited = new bool [V];
LinkedList< int > queue = new LinkedList< int >();
visited[s] = true ;
queue.AddLast(s);
IEnumerator i;
while (queue.Count != 0)
{
s = queue.First.Value;
queue.RemoveFirst();
int n;
i = adj[s].GetEnumerator();
while (i.MoveNext())
{
n = ( int )i.Current;
if (n == d)
return true ;
if (!visited[n])
{
visited[n] = true ;
queue.AddLast(n);
}
}
}
return false ;
}
public static void Main( string [] args)
{
Graph g = new Graph(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);
int u = 1;
int v = 3;
if (g.isReachable(u, v))
Console.WriteLine( "There is a path from " + u + " to " + v);
else
Console.WriteLine( "There is no path from " + u + " to " + v);
u = 3;
v = 1;
if (g.isReachable(u, v))
Console.WriteLine( "There is a path from " + u + " to " + v);
else
Console.WriteLine( "There is no path from " + u + " to " + v);
}
}
|
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 isReachable(s,d)
{
let temp;
let visited = new Array(V);
for (let i = 0; i < V; i++)
visited[i] = false ;
let queue = [];
visited[s] = true ;
queue.push(s);
while (queue.length != 0)
{
n = queue.shift();
if (n == d)
return true ;
for (let i = 0; i < adj[n].length; i++)
{
if (visited[adj[n][i]] == false )
{
queue.push(adj[n][i]);
visited[adj[n][i]] = true ;
}
}
}
return false ;
}
Graph(4);
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 2);
addEdge(2, 0);
addEdge(2, 3);
addEdge(3, 3);
let u = 1;
let v = 3;
if (isReachable(u, v))
document.write( "There is a path from " + u + " to " + v+ "<br>" );
else
document.write( "There is no path from " + u + " to " + v+ "<br>" );
u = 3;
v = 1;
if (isReachable(u, v))
document.write( "There is a path from " + u + " to " + v+ "<br>" );
else
document.write( "There is no path from " + u + " to " + v+ "<br>" );
</script>
|
Output
There is a path from 1 to 3
There is no path from 3 to 1
Complexity Analysis:
- Time Complexity: O(V+E) where V is number of vertices in the graph and E is number of edges in the graph.
- Space Complexity: O(V).
There can be atmost V elements in the queue. So the space needed is O(V).
DFS Algorithm:
- if start==end return 1 since we have to reached our destination.
- Mark start as visited.
- Traverse directly connected vertices of start and recur the function dfs for every such unexplored vertex.
- return 0 if we do not reach our destination.
Implementation:
C++14
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> adj[100000];
bool visited[100000];
bool dfs( int start, int end)
{
if (start == end)
return true ;
visited[start] = 1;
for ( auto x : adj[start]) {
if (!visited[x])
if (dfs(x, end))
return true ;
}
return false ;
}
int main()
{
int V = 4;
vector<ll> members = { 2, 5, 7, 9 };
int E = 4;
vector<pair<ll, ll> > connections
= { { 2, 9 }, { 7, 2 }, { 7, 9 }, { 9, 5 } };
for ( int i = 0; i < E; i++)
adj[connections[i].first].push_back(
connections[i].second);
int sender = 7, receiver = 9;
if (dfs(sender, receiver))
cout << "1" ;
else
cout << "0" ;
return 0;
}
|
Java
import java.util.*;
public class GFG {
public static Vector<Integer> adj[] = new Vector[ 100000 ];
public static int [] visited = new int [ 100000 ];
static boolean dfs( int start, int end)
{
if (start == end){
return true ;
}
visited[start] = 1 ;
for ( int i = 0 ; i < adj[start].size(); i++){
int x = adj[start].get(i);
if (visited[x] == 0 ){
if (dfs(x, end)){
return true ;
}
}
}
return false ;
}
public static void main(String[] args) {
int V = 4 ;
int [] members = { 2 , 5 , 7 , 9 };
int E = 4 ;
int [][] connections = { { 2 , 9 }, { 7 , 2 }, { 7 , 9 }, { 9 , 5 } };
for ( int i = 0 ;i< 100000 ;i++) {
adj[i] = new Vector<>();
}
for ( int i = 0 ; i < E; i++){
adj[connections[i][ 0 ]].add(connections[i][ 1 ]);
}
int sender = 7 ;
int receiver = 9 ;
if (dfs(sender, receiver) == true ){
System.out.println( "1" );
}
else {
System.out.println( "0" );
}
}
}
|
Python3
from typing import List , Tuple
def dfs(start: int , end: int , visited: List [ bool ], V: int ) - > bool :
if start = = end:
return True
visited[start] = True
for x in adj[start]:
if not visited[x]:
if dfs(x, end, visited, V):
return True
return False
if __name__ = = '__main__' :
V = 4
members = [ 2 , 5 , 7 , 9 ]
E = 4
connections = [ ( 2 , 9 ), ( 7 , 2 ), ( 7 , 9 ), ( 9 , 5 ) ]
member_to_index = {member: i for i, member in enumerate (members)}
adj = [[] for _ in range (V)]
for a, b in connections:
a = member_to_index[a]
b = member_to_index[b]
adj[a].append(b)
sender = member_to_index[ 7 ]
receiver = member_to_index[ 9 ]
visited = [ False ] * V
if dfs(sender, receiver, visited, V):
print ( "1" )
else :
print ( "0" )
|
C#
using System;
using System.Collections.Generic;
public class GFG {
public static bool [] visited = new bool [100000];
public static LinkedList< int >[] adj = new LinkedList< int >[100000];
static bool dfs( int start, int end)
{
if (start == end){
return true ;
}
visited[start] = true ;
foreach ( var x in adj[start]){
if (visited[x] == false )
if (dfs(x, end) == true )
return true ;
}
return false ;
}
static void Main() {
int V = 4;
int [] members = { 2, 5, 7, 9 };
int E = 4;
int [,] connections = { { 2, 9 }, { 7, 2 }, { 7, 9 }, { 9, 5 } };
for ( int i = 0; i < 100000; i++)
adj[i] = new LinkedList< int >();
for ( int i = 0; i < E; i++){
adj[connections[i,0]].AddLast(connections[i,1]);
}
int sender = 7;
int receiver = 9;
if (dfs(sender, receiver) == true ){
Console.WriteLine( "1" );
}
else {
Console.WriteLine( "0" );
}
}
}
|
JavaScript
let adj = Array.from(Array(100000), () => new Array());
let visited = new Array(100000);
function dfs(start, end) {
if (start == end) return true ;
visited[start] = 1;
for (y in adj[start]) {
x = adj[start][y];
if (!visited[x]) if (dfs(x, end)) return true ;
}
return false ;
}
let V = 4;
members = [2, 5, 7, 9];
let E = 4;
connections = [
[2, 9],
[7, 2],
[7, 9],
[9, 5],
];
for (let i = 0; i < E; i++)
adj[connections[i][0]].push(connections[i][1]);
let sender = 7,
receiver = 9;
if (dfs(sender, receiver)) console.log( "1" );
else console.log( "0" );
|
Complexity Analysis:
Time Complexity: O(V+E) where V is number of vertices in the graph and E is number of edges in the graph.
Space Complexity: O(V).
There can be atmost V elements in the stack. So the space needed is O(V).
Trade-offs between BFS and DFS:
Breadth-First search can be useful to find the shortest path between nodes, and depth-first search may traverse one adjacent node very deeply before ever going into immediate neighbours.
As an exercise, try an extended version of the problem where the complete path between two vertices is also needed.
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...