Given a Directed Acyclic Graph (DAG) with V vertices labeled from 0 to V-1.The graph is represented using an adjacency list where adj[i] lists all nodes connected to node. Find any Topological Sorting of that Graph.
In topological sorting, node u will always appear before node v if there is a directed edge from node u towards node v(u -> v).
The Output will be True if your topological sort is correct otherwise it will be False.
Input: V = 6,adj=[ [ ], [ ], [3], [1], [0,1], [0,2] ]
Output: [5, 4, 2, 3, 1, 0]
Explanation: A graph may have multiple topological sortings.
The result is one of them. The necessary conditions
for the ordering are:
According to edge 5 -> 0, node 5 must appear before node 0 in the ordering.
According to edge 4 -> 0, node 4 must appear before node 0 in the ordering.
According to edge 5 -> 2, node 5 must appear before node 2 in the ordering.
According to edge 2 -> 3, node 2 must appear before node 3 in the ordering.
According to edge 3 -> 1, node 3 must appear before node 1 in the ordering.
According to edge 4 -> 1, node 4 must appear before node 1 in the ordering.
The above result satisfies all the necessary conditions.
[4, 5, 2, 3, 1, 0] is also one such topological sorting
that satisfies all the conditions.
Input: V = 4, adj=[ [ ], [0], [0], [0] ]
Output: [3, 2, 1, 0]
Explanation: The necessary conditions for the ordering are:
For edge 1 -> 0 node 1 must appear before node 0.
For edge 2 -> 0 node 1 must appear before node 0.
For edge 3 -> 0 node 1 must appear before node 0.
Input: V = 3, adj=[[1], [2]]
The topological sorting of a directed acyclic graph is nothing but the linear ordering of vertices such that if there is an edge between node u and v(u -> v), node u appears before v in that ordering.
#include <bits/stdc++.h>
using namespace std;
class Solution {
private:
// Function to perform DFS traversal
void dfs(int node, vector<int> adj[],
vector<int> &vis,
stack <int> &st) {
// Mark the node as visited
vis[node] = 1;
// Traverse all the neighbors
for(auto it : adj[node]) {
// If not visited, recursively perform DFS.
if(vis[it] == 0) dfs(it, adj, vis, st);
}
/* Add the current node to stack
once all the nodes connected to it
have been processed */
st.push(node);
}
public:
/* Function to return list containing
vertices in Topological order */
vector<int> topoSort(int V, vector<int> adj[])
{
// To store the result
vector <int> ans;
/* Stack to store processed
nodes in reverse order */
stack <int> st;
// Visited array
vector<int> vis(V, 0);
// Traverse the graph
for(int i=0; i<V; i++) {
// Start DFS traversal for unvisited node
if(!vis[i]) {
dfs(i, adj, vis, st);
}
}
// Until the stack is empty
while(!st.empty()) {
// Add the top of stack to result
ans.push_back(st.top());
// Pop the top node
st.pop();
}
// Return the result
return ans;
}
};
int main() {
int V = 6;
vector<int> adj[V] = {
{},
{},
{3},
{1},
{0,1},
{0,2}
};
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to return the
topological sorting of given graph */
vector<int> ans = sol.topoSort(V, adj);
// Output
cout << "The topological sorting of the given graph is: \n";
for(int i=0; i < V; i++) {
cout << ans[i] << " ";
}
return 0;
}
import java.util.*;
class Solution {
// Function to perform DFS traversal
private void dfs(int node, List<Integer> adj[],
int[] vis, Stack<Integer> st) {
// Mark the node as visited
vis[node] = 1;
// Traverse all the neighbors
for (int it : adj[node]) {
// If not visited, recursively perform DFS.
if (vis[it] == 0) {
dfs(it, adj, vis, st);
}
}
/* Add the current node to stack
once all the nodes connected to it
have been processed */
st.push(node);
}
/* Function to return array containing
vertices in Topological order */
public int[] topoSort(int V, List<Integer> adj[]) {
// To store the result
int[] ans = new int[V];
/* Stack to store processed
nodes in reverse order */
Stack<Integer> st = new Stack<>();
// Visited array
int[] vis = new int[V];
// Traverse the graph
for (int i = 0; i < V; i++) {
// Start DFS traversal for unvisited node
if (vis[i] == 0) {
dfs(i, adj, vis, st);
}
}
// Until the stack is empty
for (int i = 0; i < V; i++) {
// Add the top of stack to result
ans[i] = st.pop();
}
// Return the result
return ans;
}
}
class Main {
public static void main(String[] args) {
int V = 6;
List<Integer> adj[] = new ArrayList[V];
for (int i = 0; i < V; i++) {
adj[i] = new ArrayList<>();
}
adj[2].add(3);
adj[3].add(1);
adj[4].add(0);
adj[4].add(1);
adj[5].add(0);
adj[5].add(2);
/* Creating an instance of
Solution class */
Solution sol = new Solution();
/* Function call to return the
topological sorting of given graph */
int[] ans = sol.topoSort(V, adj);
// Output
System.out.println("The topological sorting of the given graph is:");
for (int i = 0; i < V; i++) {
System.out.print(ans[i] + " ");
}
}
}
class Solution:
# Function to perform DFS traversal
def dfs(self, node, adj, vis, st):
# Mark the node as visited
vis[node] = 1
# Traverse all the neighbors
for it in adj[node]:
# If not visited, recursively perform DFS.
if vis[it] == 0:
self.dfs(it, adj, vis, st)
# Add the current node to stack
# once all the nodes connected to it
# have been processed
st.append(node)
# Function to return list containing
# vertices in Topological order
def topoSort(self, V, adj):
# To store the result
ans = []
# Stack to store processed
# nodes in reverse order
st = []
# Visited array
vis = [0] * V
# Traverse the graph
for i in range(V):
# Start DFS traversal for unvisited node
if vis[i] == 0:
self.dfs(i, adj, vis, st)
# Until the stack is empty
while st:
# Add the top of stack to result
ans.append(st.pop())
# Return the result
return ans
if __name__ == "__main__":
V = 6
adj = [
[],
[],
[3],
[1],
[0, 1],
[0, 2]
]
# Creating an instance of
# Solution class
sol = Solution()
# Function call to return the
# topological sorting of given graph
ans = sol.topoSort(V, adj)
# Output
print("The topological sorting of the given graph is:")
for i in range(V):
print(ans[i], end=" ")
class Solution {
// Function to perform DFS traversal
dfs(node, adj, vis, st) {
// Mark the node as visited
vis[node] = 1;
// Traverse all the neighbors
for (let it of adj[node]) {
// If not visited, recursively perform DFS.
if (vis[it] === 0) this.dfs(it, adj, vis, st);
}
// Add the current node to stack
// once all the nodes connected to it
// have been processed
st.push(node);
}
// Function to return list containing
// vertices in Topological order
topoSort(V, adj) {
// To store the result
let ans = [];
// Stack to store processed
// nodes in reverse order
let st = [];
// Visited array
let vis = new Array(V).fill(0);
// Traverse the graph
for (let i = 0; i < V; i++) {
// Start DFS traversal for unvisited node
if (vis[i] === 0) {
this.dfs(i, adj, vis, st);
}
}
// Until the stack is empty
while (st.length > 0) {
// Add the top of stack to result
ans.push(st.pop());
}
// Return the result
return ans;
}
}
// Main function to test the code
const main = () => {
const V = 6;
const adj = [
[],
[],
[3],
[1],
[0, 1],
[0, 2]
];
// Creating an instance of
// Solution class
const sol = new Solution();
// Function call to return the
// topological sorting of given graph
const ans = sol.topoSort(V, adj);
// Output
console.log("The topological sorting of the given graph is:");
for (let i = 0; i < V; i++) {
console.log(ans[i] + " ");
}
};
// Call the main function
main();
Time Complexity: O(V+E) (where V and E represent the number of nodes and edges in the graph)
A simple DFS traversal takes O(V+E) time.
Space Complexity: O(V)
The stack will store at most V nodes taking O(V) space and the array to store the topological sort takes O(V) space.
The topological sorting of a directed acyclic graph is nothing but the linear ordering of vertices such that if there is an edge between node u and v(u -> v), node u appears before v in that ordering.
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
/* Function to return the topological
sorting of given graph */
vector<int> topoSort(int V, vector<int> adj[]) {
// To store the result
vector<int> ans;
// To store the In-degrees of nodes
vector<int> inDegree(V, 0);
// Calculating the In-degree of the given graph
for(int i=0; i<V; i++) {
for(auto it : adj[i]) inDegree[it]++;
}
// Queue to facilitate BFS
queue<int> q;
// Add the nodes with no in-degree to queue
for(int i=0; i<V; i++) {
if(inDegree[i] == 0) q.push(i);
}
// Until the queue is empty
while(!q.empty()) {
// Get the node
int node = q.front();
// Add it to the answer
ans.push_back(node);
q.pop();
// Traverse the neighbours
for(auto it : adj[node]) {
// Decrement the in-degree
inDegree[it]--;
/* Add the node to queue if
its in-degree becomes zero */
if(inDegree[it] == 0) q.push(it);
}
}
// Return the result
return ans;
}
};
int main() {
int V = 6;
vector<int> adj[V] = {
{},
{},
{3},
{1},
{0,1},
{0,2}
};
/* Creating an instance of
Solution class */
Solution sol;
/* Function call to return the
topological sorting of given graph */
vector<int> ans = sol.topoSort(V, adj);
// Output
cout << "The topological sorting of the given graph is: \n";
for(int i=0; i < V; i++) {
cout << ans[i] << " ";
}
return 0;
}
import java.util.*;
class Solution {
/* Function to return the topological
sorting of given graph */
public int[] topoSort(int V, List<Integer> adj[]) {
// To store the result
int[] ans = new int[V];
// To store the In-degrees of nodes
int[] inDegree = new int[V];
// Calculating the In-degree of the given graph
for (int i = 0; i < V; i++) {
for (int it : adj[i]) inDegree[it]++;
}
// Queue to facilitate BFS
Queue<Integer> q = new LinkedList<>();
// Add the nodes with no in-degree to queue
for (int i = 0; i < V; i++) {
if (inDegree[i] == 0) q.add(i);
}
int index = 0; // Index to store elements in ans array
// Until the queue is empty
while (!q.isEmpty()) {
// Get the node
int node = q.poll();
// Add it to the answer
ans[index++] = node;
// Traverse the neighbours
for (int it : adj[node]) {
// Decrement the in-degree
inDegree[it]--;
/* Add the node to queue if
its in-degree becomes zero */
if (inDegree[it] == 0) q.add(it);
}
}
// Return the result
return ans;
}
}
class Main {
public static void main(String[] args) {
int V = 6;
List<Integer> adj[] = new ArrayList[V];
for (int i = 0; i < V; i++) {
adj[i] = new ArrayList<>();
}
adj[2].add(3);
adj[3].add(1);
adj[4].add(0);
adj[4].add(1);
adj[5].add(0);
adj[5].add(2);
/* Creating an instance of
Solution class */
Solution sol = new Solution();
/* Function call to return the
topological sorting of given graph */
int[] ans = sol.topoSort(V, adj);
// Output
System.out.println("The topological sorting of the given graph is:");
for (int i = 0; i < V; i++) {
System.out.print(ans[i] + " ");
}
}
}
from collections import deque
class Solution:
# Function to return the topological
# sorting of given graph
def topoSort(self, V, adj):
# To store the result
ans = []
# To store the In-degrees of nodes
inDegree = [0] * V
# Calculating the In-degree of the given graph
for i in range(V):
for it in adj[i]:
inDegree[it] += 1
# Queue to facilitate BFS
q = deque()
# Add the nodes with no in-degree to queue
for i in range(V):
if inDegree[i] == 0:
q.append(i)
# Until the queue is empty
while q:
# Get the node
node = q.popleft()
# Add it to the answer
ans.append(node)
# Traverse the neighbours
for it in adj[node]:
# Decrement the in-degree
inDegree[it] -= 1
# Add the node to queue if
# its in-degree becomes zero
if inDegree[it] == 0:
q.append(it)
# Return the result
return ans
if __name__ == "__main__":
V = 6
adj = [
[],
[],
[3],
[1],
[0,1],
[0,2]
]
# Creating an instance of
# Solution class
sol = Solution()
# Function call to return the
# topological sorting of given graph
ans = sol.topoSort(V, adj)
# Output
print("The topological sorting of the given graph is:")
for i in range(V):
print(ans[i], end=" ")
class Solution {
/* Function to return the topological
sorting of given graph */
topoSort(V, adj) {
// To store the result
let ans = [];
// To store the In-degrees of nodes
let inDegree = new Array(V).fill(0);
// Calculating the In-degree of the given graph
for (let i = 0; i < V; i++) {
for (let it of adj[i]) inDegree[it]++;
}
// Queue to facilitate BFS
let q = [];
// Add the nodes with no in-degree to queue
for (let i = 0; i < V; i++) {
if (inDegree[i] === 0) q.push(i);
}
// Until the queue is empty
while (q.length > 0) {
// Get the node
let node = q.shift();
// Add it to the answer
ans.push(node);
// Traverse the neighbours
for (let it of adj[node]) {
// Decrement the in-degree
inDegree[it]--;
/* Add the node to queue if
its in-degree becomes zero */
if (inDegree[it] === 0) q.push(it);
}
}
// Return the result
return ans;
}
}
// Main function to test the code
const main = () => {
const V = 6;
const adj = [
[],
[],
[3],
[1],
[0, 1],
[0, 2]
];
/* Creating an instance of
Solution class */
const sol = new Solution();
/* Function call to return the
topological sorting of given graph */
const ans = sol.topoSort(V, adj);
// Output
console.log("The topological sorting of the given graph is:");
for (let i = 0; i < V; i++) {
console.log(ans[i] + " ");
}
};
// Call the main function
main();
Time Complexity: O(V+E) (where V and E represent the number of nodes and edges in the graph)
A simple BFS traversal takes O(V+E) time.
Space Complexity: O(V)
Array to store in-degrees require O(V) space and queue space will store O(V) nodes at maximum.
Q: Why is topological sorting only possible for DAGs?
A: Cycles prevent a valid ordering, as no node in a cycle can appear before the others.
Q: How does DFS ensure topological sorting?
A: Post-order traversal ensures a node is pushed to the stack only after visiting all its children, giving the correct order when reversed.
Q: Can DFS and BFS give different valid topological sorts?
A: Yes, as long as all u → v constraints are satisfied, multiple valid orderings exist.
Q: How would this change if the graph was weighted?
A: Topological sorting remains the same, but it can be used to find shortest/longest paths in DAGs.