Wednesday, July 3, 2024
HomeData ModellingData Structure & AlgorithmCheck if we can visit all other nodes from any node in...

Check if we can visit all other nodes from any node in given Directed Graph

Given N nodes, where each of them is numbered from 0 to N ā€“ 1, and array edges, where there is a directed edge from edges[i][0] to edges[i][1], the task is to find whether we can travel from any node to all other nodes or not.

Examples:

Input: N = 2, edges[] = {{0, 1}, {1, 0}};
Output: True
Explanation: We can go to node 0 from 1 and node 1 from 0

Input: N = 3, edges[] = {{1, 0}};
Output: False

An approach using Kosarajuā€™s algorithm:

An idea of solving this problem is to think in terms of finding strongly connected component (SCC) for directed graph, We know that a directed graph is strongly connected if there is a path between all pairs of vertices.Ā 

So if there is only a single SCC then only we can visit all the nodes from any other node. The number of SCC can be found using Kosarajuā€™s algorithm.

Follow the steps below to implement the above idea:

  • Create adjacency list adj1 for storing the graph.
  • Do DFS in random order of vertices and store the visited vertices in a stack stk while backtracking.
  • Reverse the direction of all edges of the adj1 graph and store the newly created graph in adj2.
  • Do dfs2 in order of stack and keep count of the strongly connected components in variable scc.
  • Check the count of scc:
    • If the count of scc is greater than 1, return false.
    • Otherwise, return true.

Below is the implementation of the above approach:

C++




// C++ code to implement above approach
Ā 
#include <bits/stdc++.h>
using namespace std;
Ā 
// Function to find components
void randomOrderDfs(int i, vector<vector<int> >& adj,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā vector<bool>& visited, stack<int>& stk)
{
Ā Ā Ā Ā visited[i] = true;
Ā 
Ā Ā Ā Ā for (auto child : adj[i]) {
Ā Ā Ā Ā Ā Ā Ā Ā if (visited[child] == false) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā randomOrderDfs(child, adj, visited, stk);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā stk.push(i);
}
Ā 
// Function to traverse in the reversed graph
void dfs2(int i, vector<vector<int> >& adj,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā vector<bool>& visited)
{
Ā Ā Ā Ā visited[i] = true;
Ā 
Ā Ā Ā Ā for (auto child : adj[i]) {
Ā Ā Ā Ā Ā Ā Ā Ā if (visited[child] == false) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dfs2(child, adj, visited);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
}
Ā 
// Function to check if it is possible
// to reach all other nodes from any node
bool isTourPossible(int n, vector<vector<int> >& roads)
{
Ā Ā Ā Ā // adj1 stores adjacency matrix of
Ā Ā Ā Ā // original graph adj2 stores
Ā Ā Ā Ā // adjacency matrix of original graph
Ā Ā Ā Ā // by reversing direction of all edges
Ā Ā Ā Ā vector<vector<int> > adj1(n), adj2(n);
Ā 
Ā Ā Ā Ā // Create graph
Ā Ā Ā Ā for (auto i : roads) {
Ā Ā Ā Ā Ā Ā Ā Ā adj1[i[0]].push_back(i[1]);
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā vector<bool> visited1(n, false), visited2(n, false);
Ā Ā Ā Ā stack<int> stk;
Ā 
Ā Ā Ā Ā // Random dfs and maintain stack
Ā Ā Ā Ā // at backtracking (endpoint)
Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā if (visited1[i] == false) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā randomOrderDfs(i, adj1, visited1, stk);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā // Reverse all the edges
Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā for (auto child : adj1[i]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj2[child].push_back(i);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā // scc for counting the number of
Ā Ā Ā Ā // strongly connected component
Ā Ā Ā Ā int scc = 0;
Ā 
Ā Ā Ā Ā // Make second dfs at order of stk
Ā Ā Ā Ā while (stk.size() > 0) {
Ā Ā Ā Ā Ā Ā Ā Ā int node = stk.top();
Ā Ā Ā Ā Ā Ā Ā Ā if (visited2[node]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stk.pop();
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā else {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dfs2(node, adj2, visited2);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stk.pop();
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā scc++;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (scc > 1)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return false;
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā return true;
}
Ā 
// Driver code
int main()
{
Ā Ā Ā Ā int N = 2;
Ā Ā Ā Ā vector<vector<int> > edges = { { 0, 1 }, { 1, 0 } };
Ā 
Ā Ā Ā Ā // Function call
Ā Ā Ā Ā bool result = isTourPossible(N, edges);
Ā 
Ā Ā Ā Ā if (result) {
Ā Ā Ā Ā Ā Ā Ā Ā cout << "True" << endl;
Ā Ā Ā Ā }
Ā Ā Ā Ā else {
Ā Ā Ā Ā Ā Ā Ā Ā cout << "False" << endl;
Ā Ā Ā Ā }
Ā Ā Ā Ā return 0;
}


Java




// Java program to implement the approach
import java.io.*;
import java.util.*;
Ā 
// Function to find components
class GFG
{
Ā Ā Ā 
Ā Ā Ā Ā // Function to find components
Ā Ā Ā Ā static void
Ā Ā Ā Ā randomOrderDfs(int i,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā ArrayList<ArrayList<Integer> > adj,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā boolean[] visited, Stack<Integer> stk)
Ā Ā Ā Ā {
Ā Ā Ā Ā Ā Ā Ā Ā visited[i] = true;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < adj.get(i).size(); j++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā int child = adj.get(i).get(j);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (visited[child] == false) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā randomOrderDfs(child, adj, visited, stk);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā stk.push(i);
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā // Function to traverse in the reversed graph
Ā Ā Ā Ā static void dfs2(int i,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā ArrayList<ArrayList<Integer> > adj,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā boolean[] visited)
Ā Ā Ā Ā {
Ā Ā Ā Ā Ā Ā Ā Ā visited[i] = true;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < adj.get(i).size(); j++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā int child = adj.get(j).get(0);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (visited[child] == false) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dfs2(child, adj, visited);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā // Function to check if it is possible
Ā Ā Ā Ā // to reach all other nodes from any node
Ā Ā Ā Ā static boolean isTourPossible(int n, int[][] roads)
Ā Ā Ā Ā {
Ā Ā Ā Ā Ā Ā Ā Ā // adj1 stores adjacency matrix of
Ā Ā Ā Ā Ā Ā Ā Ā // original graph adj2 stores
Ā Ā Ā Ā Ā Ā Ā Ā // adjacency matrix of original graph
Ā Ā Ā Ā Ā Ā Ā Ā // by reversing direction of all edges
Ā Ā Ā Ā Ā Ā Ā Ā ArrayList<ArrayList<Integer> > adj1
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā = new ArrayList<>();
Ā Ā Ā Ā Ā Ā Ā Ā ArrayList<ArrayList<Integer> > adj2
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā = new ArrayList<>();
Ā Ā Ā Ā Ā Ā Ā Ā ;
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj1.add(new ArrayList<Integer>());
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj2.add(new ArrayList<Integer>());
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā // Create graph
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj1.get(roads[i][0]).add(roads[i][1]);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā boolean[] visited1 = new boolean[n];
Ā Ā Ā Ā Ā Ā Ā Ā boolean[] visited2 = new boolean[n];
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā visited1[i] = false;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā visited2[i] = false;
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā Stack<Integer> stk = new Stack<Integer>();
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā // Random dfs and maintain stack
Ā Ā Ā Ā Ā Ā Ā Ā // at backtracking (endpoint)
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (visited1[i] == false) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā randomOrderDfs(i, adj1, visited1, stk);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā // Reverse all the edges
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < adj1.get(i).size(); j++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā int child = adj1.get(i).get(j);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj2.get(child).add(i);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā // scc for counting the number of
Ā Ā Ā Ā Ā Ā Ā Ā // strongly connected component
Ā Ā Ā Ā Ā Ā Ā Ā int scc = 0;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā // Make second dfs at order of stk
Ā Ā Ā Ā Ā Ā Ā Ā while (stk.size() > 0) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā int node = stk.peek();
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (visited2[node]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stk.pop();
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dfs2(node, adj2, visited2);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stk.pop();
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā scc++;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (scc > 1)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return false;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā return true;
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā // Driver code
Ā Ā Ā Ā public static void main(String[] args)
Ā Ā Ā Ā {
Ā Ā Ā Ā Ā Ā Ā Ā int N = 2;
Ā Ā Ā Ā Ā Ā Ā Ā int edges[][] = { { 0, 1 }, { 1, 0 } };
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā // Function call
Ā Ā Ā Ā Ā Ā Ā Ā boolean result = isTourPossible(N, edges);
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā if (result) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā System.out.println("True");
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā else {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā System.out.println("False");
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
}
Ā 
// This code is contributed by garg28harsh.


Python3




# Python code to implement above approach
Ā 
# Function to find components
def randomOrderDfs(i, adj, visited, stk):
Ā Ā Ā Ā visited[i] = True
Ā Ā Ā Ā for child in adj[i]:
Ā Ā Ā Ā Ā Ā Ā Ā if(visited[child] == False):
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā randomOrderDfs(child, adj, visited, stk)
Ā Ā Ā Ā stk.append(i)
Ā 
# Function to traverse in the reversed graph
def dfs2(i, adj, visited):
Ā Ā Ā Ā visited[i] = True
Ā Ā Ā Ā Ā 
Ā Ā Ā Ā for child in adj[i]:
Ā Ā Ā Ā Ā Ā Ā Ā if(visited[child] == False):
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dfs2(child, adj, visited)
Ā Ā Ā Ā Ā 
# Function to check if it is possible
# to reach all other nodes from any node
def isTourPossible(n,roads):
Ā Ā Ā Ā # adj1 stores adjacency matrix of
Ā Ā Ā Ā # original graph adj2 stores
Ā Ā Ā Ā # adjacency matrix of original graph
Ā Ā Ā Ā # by reversing direction of all edges
Ā Ā Ā Ā adj1 = [[] for i in range(n)]
Ā Ā Ā Ā adj2 = [[] for i in range(n)]
Ā Ā Ā Ā Ā 
Ā Ā Ā Ā # Create graph
Ā Ā Ā Ā for i in roads:
Ā Ā Ā Ā Ā Ā Ā Ā adj1[i[0]].append(i[1])
Ā Ā Ā Ā Ā 
Ā Ā Ā Ā visited1 = [False]*n
Ā Ā Ā Ā visited2 = [False]*n
Ā Ā Ā Ā stk = []
Ā Ā Ā Ā Ā 
Ā Ā Ā Ā # Random dfs and maintain stack
Ā Ā Ā Ā # at backtracking (endpoint)
Ā Ā Ā Ā for i in range(n):
Ā Ā Ā Ā Ā Ā Ā Ā if(visited1[i]==False):
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā randomOrderDfs(i,adj1,visited1,stk)
Ā Ā Ā Ā Ā 
Ā Ā Ā Ā # Reverse all the edges
Ā Ā Ā Ā for i in range(n):
Ā Ā Ā Ā Ā Ā Ā Ā for child in adj1[i]:
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj2[child].append(i)
Ā Ā Ā Ā Ā 
Ā Ā Ā Ā # scc for counting the number of
Ā Ā Ā Ā # strongly connected component
Ā Ā Ā Ā scc=0
Ā Ā Ā Ā Ā 
Ā Ā Ā Ā # Make second dfs at order of stk
Ā Ā Ā Ā while(len(stk) > 0):
Ā Ā Ā Ā Ā Ā Ā Ā node = stk[len(stk)-1]
Ā Ā Ā Ā Ā Ā Ā Ā if(visited2[node]):
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stk.pop()
Ā Ā Ā Ā Ā Ā Ā Ā else:
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dfs2(node,adj2,visited2)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stk.pop()
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā scc = scc + 1
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā 
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if(scc>1):
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return False
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā 
Ā Ā Ā Ā return True
Ā 
# Driver code
N = 2
edges = [[0,1],[1,0]]
Ā 
# Function call
result = isTourPossible(N,edges)
if(result):
Ā Ā Ā Ā print("True")
else:
Ā Ā Ā Ā print("False")
Ā Ā Ā Ā Ā 
# This code is contributed by Pushpesh Raj.


C#




// C# program to implement the approach
using System;
using System.Collections.Generic;
Ā 
// Function to find components
class Program {
Ā Ā // Function to find components
Ā Ā Ā Ā static void RandomOrderDfs(int i, List<List<int> > adj,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bool[] visited,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Stack<int> stk)
Ā Ā Ā Ā {
Ā Ā Ā Ā Ā Ā Ā Ā visited[i] = true;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < adj[i].Count; j++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā int child = adj[i][j];
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (!visited[child]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā RandomOrderDfs(child, adj, visited, stk);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā stk.Push(i);
Ā Ā Ā Ā }
Ā Ā Ā Ā // Function to traverse in the reversed graph
Ā Ā Ā Ā static void Dfs2(int i, List<List<int> > adj,
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā bool[] visited)
Ā Ā Ā Ā {
Ā Ā Ā Ā Ā Ā Ā Ā visited[i] = true;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < adj[i].Count; j++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā int child = adj[j][0];
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (!visited[child]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Dfs2(child, adj, visited);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā Ā Ā Ā // Function to check if it is possible
Ā Ā Ā Ā // to reach all other nodes from any node
Ā Ā Ā Ā static bool IsTourPossible(int n, int[][] roads)
Ā Ā Ā Ā {
Ā Ā Ā Ā Ā Ā Ā Ā // adj1 stores adjacency matrix of
Ā Ā Ā Ā Ā Ā Ā Ā // original graph adj2 stores
Ā Ā Ā Ā Ā Ā Ā Ā // adjacency matrix of original graph
Ā Ā Ā Ā Ā Ā Ā Ā // by reversing direction of all edges
Ā Ā Ā Ā Ā Ā Ā Ā List<List<int> > adj1 = new List<List<int> >();
Ā Ā Ā Ā Ā Ā Ā Ā List<List<int> > adj2 = new List<List<int> >();
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj1.Add(new List<int>());
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj2.Add(new List<int>());
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj1[roads[i][0]].Add(roads[i][1]);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā bool[] visited1 = new bool[n];
Ā Ā Ā Ā Ā Ā Ā Ā bool[] visited2 = new bool[n];
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā visited1[i] = false;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā visited2[i] = false;
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā Stack<int> stk = new Stack<int>();
Ā Ā Ā Ā Ā Ā Ā 
Ā Ā Ā Ā Ā Ā Ā Ā // Random dfs and maintain stack
Ā Ā Ā Ā Ā Ā Ā Ā // at backtracking (endpoint)
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (!visited1[i]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā RandomOrderDfs(i, adj1, visited1, stk);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā // Reverse all the edges
Ā Ā Ā Ā Ā Ā Ā Ā for (int i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā for (int j = 0; j < adj1[i].Count; j++) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā int child = adj1[i][j];
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj2[child].Add(i);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā int scc = 0;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā while (stk.Count > 0) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā int node = stk.Peek();
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (visited2[node]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stk.Pop();
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā else {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Dfs2(node, adj2, visited2);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā stk.Pop();
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā scc++;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (scc > 1) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return false;
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā return true;
Ā Ā Ā Ā }
Ā Ā Ā Ā // Driver code
Ā Ā Ā Ā static void Main(string[] args)
Ā Ā Ā Ā {
Ā Ā Ā Ā Ā Ā Ā Ā int N = 2;
Ā Ā Ā Ā Ā Ā Ā Ā int[][] edges = new int[][] { new int[] { 0, 1 },
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā new int[] { 1, 0 } };
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā bool result = IsTourPossible(N, edges);
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā Console.WriteLine(result ? "True" : "False");
Ā Ā Ā Ā }
}


Javascript




// JavaScript code to implement above approach
Ā 
function randomOrderDfs(i, adj, visited, stk) {
Ā Ā Ā Ā visited[i] = true;
Ā 
Ā Ā Ā Ā for (let child of adj[i]) {
Ā Ā Ā Ā Ā Ā Ā Ā if (!visited[child]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā randomOrderDfs(child, adj, visited, stk);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā stk.push(i);
}
Ā 
function dfs2(i, adj, visited) {
Ā Ā Ā Ā visited[i] = true;
Ā 
Ā Ā Ā Ā for (let child of adj[i]) {
Ā Ā Ā Ā Ā Ā Ā Ā if (!visited[child]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dfs2(child, adj, visited);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
}
Ā 
function isTourPossible(n, roads) {
Ā Ā Ā Ā // adj1 stores adjacency matrix of
Ā Ā Ā Ā // original graph adj2 stores
Ā Ā Ā Ā // adjacency matrix of original graph
Ā Ā Ā Ā // by reversing direction of all edges
Ā Ā Ā Ā let adj1 = new Array(n), adj2 = new Array(n);
Ā Ā Ā Ā for (let i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā adj1[i] = [];
Ā Ā Ā Ā Ā Ā Ā Ā adj2[i] = [];
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā // Create graph
Ā Ā Ā Ā for (let i of roads) {
Ā Ā Ā Ā Ā Ā Ā Ā adj1[i[0]].push(i[1]);
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā let visited1 = new Array(n).fill(false), visited2 = new Array(n).fill(false);
Ā Ā Ā Ā let stk = [];
Ā 
Ā Ā Ā Ā // Random dfs and maintain stack
Ā Ā Ā Ā // at backtracking (endpoint)
Ā Ā Ā Ā for (let i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā if (!visited1[i]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā randomOrderDfs(i, adj1, visited1, stk);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā // Reverse all the edges
Ā Ā Ā Ā for (let i = 0; i < n; i++) {
Ā Ā Ā Ā Ā Ā Ā Ā for (let child of adj1[i]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā adj2[child].push(i);
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā // scc for counting the number of
Ā Ā Ā Ā // strongly connected component
Ā Ā Ā Ā let scc = 0;
Ā 
Ā Ā Ā Ā // Make second dfs at order of stk
Ā Ā Ā Ā while (stk.length > 0) {
Ā Ā Ā Ā Ā Ā Ā Ā let node = stk.pop();
Ā Ā Ā Ā Ā Ā Ā Ā if (!visited2[node]) {
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā dfs2(node, adj2, visited2);
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā scc++;
Ā 
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā if (scc > 1)
Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā Ā return false;
Ā Ā Ā Ā Ā Ā Ā Ā }
Ā Ā Ā Ā }
Ā 
Ā Ā Ā Ā return true;
}
Ā 
let N = 2;
let edges = [ [0, 1], [1, 0] ];
Ā 
// Function call
let result = isTourPossible(N, edges);
Ā 
if (result) {
Ā Ā Ā Ā console.log("True");
}
else {
Ā Ā Ā Ā console.log("False");
}
// this code is contributed by dany


Output

True

Time Complexity: O(N+E), where E is the number of edges
Auxiliary Space: O(N+E)

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

Thapelo Manthata
Iā€™m a desktop support specialist transitioning into a SharePoint developer role by day and Software Engineering student by night. My superpowers include customer service, coding, the Microsoft office 365 suite including SharePoint and power platform.
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments