Given a directed graph G N nodes and E Edges consisting of nodes valued [0, N – 1] and a 2D array Edges[][2] of type {u, v} that denotes a directed edge between vertices u and v. The task is to find the nodes that are not part of any cycle in the given graph G.
Examples:
Input: N = 4, E = 4, Edges[][2] = { {0, 2}, {0, 1}, {2, 3}, {3, 0} }
Output: 1
Explanation:
From the given graph above there exists a cycle between the nodes 0 -> 2 -> 3 -> 0.
Node which doesn’t occurs in any cycle is 1.
Hence, print 1.Input: N = 6, E = 7, Edges[][2] = { {0, 1}, {0, 2}, {1, 3}, {2, 1}, {2, 5}, {3, 0}, {4, 5}}
Output: 4 5
Explanation:
From the given graph above there exists a cycle between the nodes:
1) 0 -> 1 -> 3 -> 0.
2) 0 -> 2 -> 1 -> 3 -> 0.
Nodes which doesn’t occurs in any cycle are 4 and 5.
Hence, print 4 and 5.
Naive Approach: The simplest approach is to detect a cycle in a directed graph for each node in the given graph and print only those nodes that are not a part of any cycle in the given graph.
Time Complexity: O(V * (V + E)), where V is the number of vertices and E is the number of edges.
Auxiliary Space: O(V)
Efficient Approach: To optimize the above approach, the idea is to store the intermediate node as a visited cycle node whenever any cycle in the given graph. To implement this part use an auxiliary array cyclePart[] that will store the intermediate cycle node while performing the DFS Traversal. Below are the steps:
- Initialize an auxiliary array cyclePart[] of size N, such that if cyclePart[i] = 0, then ith node doesn’t exist in any cycle.
- Initialize an auxiliary array recStack[] of size N, such that it will store the visited node in the recursion stack by marking that node as true.
- Perform the DFS Traversal on the given graph for each unvisited node and do the following:
- Now find a cycle in the given graph, whenever a cycle is found, mark the node in cyclePart[] as true as this node is a part of the cycle.
- If any node is visited in the recursive call and is recStack[node] is also true then that node is a part of the cycle then mark that node as true.
- After performing the DFS Traversal, traverse the array cyclePart[] and print all those nodes that are marked as false as these nodes are not the part of any cycle.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
class Graph {
// No. of vertices
int V;
// Stores the Adjacency List
list< int >* adj;
bool printNodesNotInCycleUtil(
int v, bool visited[], bool * rs,
bool * cyclePart);
public :
// Constructor
Graph( int V);
// Member Functions
void addEdge( int v, int w);
void printNodesNotInCycle();
}; // Function to initialize the graph Graph::Graph( int V)
{ this ->V = V;
adj = new list< int >[V];
} // Function that adds directed edges // between node v with node w void Graph::addEdge( int v, int w)
{ adj[v].push_back(w);
} // Function to perform DFS Traversal // and return true if current node v // forms cycle bool Graph::printNodesNotInCycleUtil(
int v, bool visited[],
bool * recStack, bool * cyclePart)
{ // If node v is unvisited
if (visited[v] == false ) {
// Mark the current node as
// visited and part of
// recursion stack
visited[v] = true ;
recStack[v] = true ;
// Traverse the Adjacency
// List of current node v
for ( auto & child : adj[v]) {
// If child node is unvisited
if (!visited[child]
&& printNodesNotInCycleUtil(
child, visited,
recStack, cyclePart)) {
// If child node is a part
// of cycle node
cyclePart[child] = 1;
return true ;
}
// If child node is visited
else if (recStack[child]) {
cyclePart[child] = 1;
return true ;
}
}
}
// Remove vertex from recursion stack
recStack[v] = false ;
return false ;
} // Function that print the nodes for // the given directed graph that are // not present in any cycle void Graph::printNodesNotInCycle()
{ // Stores the visited node
bool * visited = new bool [V];
// Stores nodes in recursion stack
bool * recStack = new bool [V];
// Stores the nodes that are
// part of any cycle
bool * cyclePart = new bool [V];
for ( int i = 0; i < V; i++) {
visited[i] = false ;
recStack[i] = false ;
cyclePart[i] = false ;
}
// Traverse each node
for ( int i = 0; i < V; i++) {
// If current node is unvisited
if (!visited[i]) {
// Perform DFS Traversal
if (printNodesNotInCycleUtil(
i, visited, recStack,
cyclePart)) {
// Mark as cycle node
// if it return true
cyclePart[i] = 1;
}
}
}
// Traverse the cyclePart[]
for ( int i = 0; i < V; i++) {
// If node i is not a part
// of any cycle
if (cyclePart[i] == 0) {
cout << i << " " ;
}
}
} // Function that print the nodes for // the given directed graph that are // not present in any cycle void solve( int N, int E,
int Edges[][2])
{ // Initialize the graph g
Graph g(N);
// Create a directed Graph
for ( int i = 0; i < E; i++) {
g.addEdge(Edges[i][0],
Edges[i][1]);
}
// Function Call
g.printNodesNotInCycle();
} // Driver Code int main()
{ // Given Number of nodes
int N = 6;
// Given Edges
int E = 7;
int Edges[][2] = { { 0, 1 }, { 0, 2 },
{ 1, 3 }, { 2, 1 },
{ 2, 5 }, { 3, 0 },
{ 4, 5 } };
// Function Call
solve(N, E, Edges);
return 0;
} |
// Java program for above approach import java.util.*;
import java.lang.*;
class GFG
{ static ArrayList<ArrayList<Integer>> adj;
static int V;
// Function to perform DFS Traversal
// and return true if current node v
// forms cycle
static boolean printNodesNotInCycleUtil(
int v, boolean visited[],
boolean [] recStack, boolean [] cyclePart)
{
// If node v is unvisited
if (visited[v] == false )
{
// Mark the current node as
// visited and part of
// recursion stack
visited[v] = true ;
recStack[v] = true ;
// Traverse the Adjacency
// List of current node v
for (Integer child : adj.get(v))
{
// If child node is unvisited
if (!visited[child]
&& printNodesNotInCycleUtil(
child, visited,
recStack, cyclePart))
{
// If child node is a part
// of cycle node
cyclePart[child] = true ;
return true ;
}
// If child node is visited
else if (recStack[child])
{
cyclePart[child] = true ;
return true ;
}
}
}
// Remove vertex from recursion stack
recStack[v] = false ;
return false ;
}
static void printNodesNotInCycle()
{
// Stores the visited node
boolean [] visited = new boolean [V];
// Stores nodes in recursion stack
boolean [] recStack = new boolean [V];
// Stores the nodes that are
// part of any cycle
boolean [] cyclePart = new boolean [V];
// Traverse each node
for ( int i = 0 ; i < V; i++)
{
// If current node is unvisited
if (!visited[i])
{
// Perform DFS Traversal
if (printNodesNotInCycleUtil(
i, visited, recStack,
cyclePart)) {
// Mark as cycle node
// if it return true
cyclePart[i] = true ;
}
}
}
// Traverse the cyclePart[]
for ( int i = 0 ; i < V; i++)
{
// If node i is not a part
// of any cycle
if (!cyclePart[i])
{
System.out.print(i+ " " );
}
}
}
// Function that print the nodes for
// the given directed graph that are
// not present in any cycle
static void solve( int N, int E,
int Edges[][])
{
adj = new ArrayList<>();
for ( int i = 0 ; i < N; i++)
adj.add( new ArrayList<>());
// Create a directed Graph
for ( int i = 0 ; i < E; i++)
{
adj.get(Edges[i][ 0 ]).add(Edges[i][ 1 ]);
}
// Function Call
printNodesNotInCycle();
}
// Driver function
public static void main (String[] args)
{
// Given Number of nodes
V = 6 ;
// Given Edges
int E = 7 ;
int Edges[][] = { { 0 , 1 }, { 0 , 2 },
{ 1 , 3 }, { 2 , 1 },
{ 2 , 5 }, { 3 , 0 },
{ 4 , 5 } };
// Function Call
solve(V, E, Edges);
}
} // This code is contributed by offbeat |
# Python3 program for the above approach class Graph:
# Function to initialize the graph
def __init__( self , V):
self .V = V
self .adj = [[] for i in range ( self .V)]
# Function that adds directed edges
# between node v with node w
def addEdge( self , v, w):
self .adj[v].append(w);
# Function to perform DFS Traversal
# and return True if current node v
# forms cycle
def printNodesNotInCycleUtil( self , v, visited,recStack, cyclePart):
# If node v is unvisited
if (visited[v] = = False ):
# Mark the current node as
# visited and part of
# recursion stack
visited[v] = True ;
recStack[v] = True ;
# Traverse the Adjacency
# List of current node v
for child in self .adj[v]:
# If child node is unvisited
if ( not visited[child] and self .printNodesNotInCycleUtil(child, visited,recStack, cyclePart)):
# If child node is a part
# of cycle node
cyclePart[child] = 1 ;
return True ;
# If child node is visited
elif (recStack[child]):
cyclePart[child] = 1 ;
return True ;
# Remove vertex from recursion stack
recStack[v] = False ;
return False ;
# Function that print the nodes for
# the given directed graph that are
# not present in any cycle
def printNodesNotInCycle( self ):
# Stores the visited node
visited = [ False for i in range ( self .V)];
# Stores nodes in recursion stack
recStack = [ False for i in range ( self .V)];
# Stores the nodes that are
# part of any cycle
cyclePart = [ False for i in range ( self .V)]
# Traverse each node
for i in range ( self .V):
# If current node is unvisited
if ( not visited[i]):
# Perform DFS Traversal
if ( self .printNodesNotInCycleUtil(
i, visited, recStack,
cyclePart)):
# Mark as cycle node
# if it return True
cyclePart[i] = 1 ;
# Traverse the cyclePart[]
for i in range ( self .V):
# If node i is not a part
# of any cycle
if (cyclePart[i] = = 0 ) :
print (i,end = ' ' )
# Function that print the nodes for # the given directed graph that are # not present in any cycle def solve( N, E, Edges):
# Initialize the graph g
g = Graph(N);
# Create a directed Graph
for i in range (E):
g.addEdge(Edges[i][ 0 ],
Edges[i][ 1 ]);
# Function Call
g.printNodesNotInCycle();
# Driver Code
if __name__ = = '__main__' :
# Given Number of nodes
N = 6 ;
# Given Edges
E = 7 ;
Edges = [ [ 0 , 1 ], [ 0 , 2 ],
[ 1 , 3 ], [ 2 , 1 ],
[ 2 , 5 ], [ 3 , 0 ],
[ 4 , 5 ] ];
# Function Call
solve(N, E, Edges);
# This code is contributed by rutvik_56 |
// C# program for above approach using System;
using System.Collections.Generic;
public class GFG
{ static List<List< int >> adj;
static int V;
// Function to perform DFS Traversal
// and return true if current node v
// forms cycle
static bool printNodesNotInCycleUtil(
int v, bool []visited,
bool [] recStack, bool [] cyclePart)
{
// If node v is unvisited
if (visited[v] == false )
{
// Mark the current node as
// visited and part of
// recursion stack
visited[v] = true ;
recStack[v] = true ;
// Traverse the Adjacency
// List of current node v
foreach ( int child in adj[v])
{
// If child node is unvisited
if (!visited[child]
&& printNodesNotInCycleUtil(
child, visited,
recStack, cyclePart))
{
// If child node is a part
// of cycle node
cyclePart[child] = true ;
return true ;
}
// If child node is visited
else if (recStack[child])
{
cyclePart[child] = true ;
return true ;
}
}
}
// Remove vertex from recursion stack
recStack[v] = false ;
return false ;
}
static void printNodesNotInCycle()
{
// Stores the visited node
bool [] visited = new bool [V];
// Stores nodes in recursion stack
bool [] recStack = new bool [V];
// Stores the nodes that are
// part of any cycle
bool [] cyclePart = new bool [V];
// Traverse each node
for ( int i = 0; i < V; i++)
{
// If current node is unvisited
if (!visited[i])
{
// Perform DFS Traversal
if (printNodesNotInCycleUtil(
i, visited, recStack,
cyclePart)) {
// Mark as cycle node
// if it return true
cyclePart[i] = true ;
}
}
}
// Traverse the cyclePart[]
for ( int i = 0; i < V; i++)
{
// If node i is not a part
// of any cycle
if (!cyclePart[i])
{
Console.Write(i+ " " );
}
}
}
// Function that print the nodes for
// the given directed graph that are
// not present in any cycle
static void solve( int N, int E,
int [,]Edges)
{
adj = new List<List< int >>();
for ( int i = 0; i < N; i++)
adj.Add( new List< int >());
// Create a directed Graph
for ( int i = 0; i < E; i++)
{
adj[Edges[i,0]].Add(Edges[i,1]);
}
// Function Call
printNodesNotInCycle();
}
// Driver function
public static void Main(String[] args)
{
// Given Number of nodes
V = 6;
// Given Edges
int E = 7;
int [,]Edges = { { 0, 1 }, { 0, 2 },
{ 1, 3 }, { 2, 1 },
{ 2, 5 }, { 3, 0 },
{ 4, 5 } };
// Function Call
solve(V, E, Edges);
}
} // This code contributed by shikhasingrajput |
<script> // JavaScript program for the above approach class Graph{ // Function to initialize the graph
constructor(V){
this .V = V
this .adj = new Array(V).fill(0).map(()=>[])
}
// Function that adds directed edges
// between node v with node w
addEdge(v, w){
this .adj[v].push(w);
}
// Function to perform DFS Traversal
// and return true if current node v
// forms cycle
printNodesNotInCycleUtil(v, visited,recStack, cyclePart){
// If node v is unvisited
if (visited[v] == false ){
// Mark the current node as
// visited and part of
// recursion stack
visited[v] = true ;
recStack[v] = true ;
// Traverse the Adjacency
// List of current node v
for (let child of this .adj[v]){
// If child node is unvisited
if (visited[child] == false && this .printNodesNotInCycleUtil(child, visited,recStack, cyclePart)){
// If child node is a part
// of cycle node
cyclePart[child] = 1;
return true ;
}
// If child node is visited
else if (recStack[child]){
cyclePart[child] = 1;
return true ;
}
}
}
// Remove vertex from recursion stack
recStack[v] = false ;
return false ;
}
// Function that print the nodes for
// the given directed graph that are
// not present in any cycle
printNodesNotInCycle(){
// Stores the visited node
let visited = new Array( this .V).fill( false );
// Stores nodes in recursion stack
let recStack = new Array( this .V).fill( false );
// Stores the nodes that are
// part of any cycle
let cyclePart = new Array( this .V).fill( false )
// Traverse each node
for (let i=0;i< this .V;i++){
// If current node is unvisited
if (visited[i] == false ){
// Perform DFS Traversal
if ( this .printNodesNotInCycleUtil(
i, visited, recStack,
cyclePart))
// Mark as cycle node
// if it return true
cyclePart[i] = 1;
}
}
// Traverse the cyclePart[]
for (let i=0;i< this .V;i++){
// If node i is not a part
// of any cycle
if (cyclePart[i] == 0)
document.write(i, ' ' )
}
}
} // Function that print the nodes for // the given directed graph that are // not present in any cycle function solve(N, E, Edges){
// Initialize the graph g
let g = new Graph(N);
// Create a directed Graph
for (let i=0;i<E;i++){
g.addEdge(Edges[i][0],
Edges[i][1]);
}
// Function Call
g.printNodesNotInCycle();
} // Driver Code // Given Number of nodes let N = 6; // Given Edges let E = 7; let Edges = [ [ 0, 1 ], [ 0, 2 ], [ 1, 3 ], [ 2, 1 ],
[ 2, 5 ], [ 3, 0 ],
[ 4, 5 ] ];
// Function Call solve(N, E, Edges) // This code is contributed by shinjanpatra </script> |
4 5
Time Complexity: O(V + E)
Space Complexity: O(V)