You are given a Weighted Directed Acyclic Graph (DAG) consisting of ‘N’ nodes and ‘E’ directed edges. Nodes are numbered from 0 to ’N’-1. You are also given a source node ‘Src’ in it. Your task is to find the longest distances from ‘Src’ to all the nodes in the given graph.
Return an array of ‘N’ integers where ‘ith’ integer gives the maximum distance of the node ‘i’ from the source node ‘Src’.
A Directed Acyclic Graph (DAG) is a directed graph that contains no cycles.
Note:
Print -1 if a node is not reachable from the given source node.
Example:
Consider the following DAG consists of 5 nodes and 7 edges, Let the source node ‘Src’ be 0.
Then the maximum distance of node 0 from the source node 0 is 0. (the distance of a node from itself is always 0).
The maximum distance of node 1 from the source node 0 is 3. The path that gives this maximum distance is 0 -> 1.
The maximum distance of node 2 from the source node 0 is 10. The path that gives this maximum distance is 0 -> 2.
The maximum distance of node 3 from the source node 0 is 15. The path that gives this maximum distance is 0 -> 2 -> 3.
The maximum distance of node 4 from the source node 0 is 54. The path that gives this maximum distance is 0 -> 1 -> 4.
Thus we should print 0 3 10 15 54
Input format:
The first line of input contains an integer ‘T’ denoting the number of test cases. then ‘T’ test cases follow.
The first line of each test case consists of three space-separated integers ‘N’, ‘E’, and ‘Src’ representing the number of nodes, number of edges, and the given source node in the given DAG respectively.
The next ‘E’ lines consist of three space-separated integers ‘U’, ‘V’, ‘W’ representing that there is a directed edge from node U to V having weight ‘W’.
Output format :
For each test case, print ‘N’ space-separated integers where ’ith’ integer gives the maximum distance of node ‘i’ from the source node ‘Src’.
The output of each test case will be printed in a new line.
Note:
You do not need to print anything, it has already been taken care of. Just implement the given function.
Constraints:
1 <= T <= 50
1 <= N <= 10^4
0 <= E <= 10^4
0 <= Src <= N-1
0 <= U, V <= N-1
1 <= W <= 10^5
Where ‘T’ is the total number of test cases, ‘N’, ‘E’, and ‘Src’ representing the number of nodes, number of edges, and the given source node in the given DAG respectively. ‘U’, ‘V’, ‘W’ represents that there is a directed edge from node U to V having weight ‘W’.
Time limit: 1 sec
This is a problem of topological sorting.
Time complexity of topological sorting is O(V+E). After finding topological order, the algorithm process all vertices and for every vertex, it runs a loop for ...read more
First we create an integer array ‘maxDistances’ of size ‘N’ and fill it with -1, maxDistances[i] will give the maximum distance of node ‘i’ from the given source node. We will then recursiv...read more
Topological Sorting of DAG is a linear ordering of vertices such that for every directed edge from vertex ‘u’ to vertex ‘v’, vertex ‘u’ comes before ‘v’ in the ordering. Topological Sorting for a graph is not possible if the graph is not a DAG. We can find topological sorting of any DAG using this algorithm.
We can solve this problem of finding the longest paths in a directed graph in linear time if we process nodes in topological order, and update distances of their adjacent.
Note that if the graph is not DAG, then this problem is an NP-hard problem.
Algorithm
- Create an adjacency list ‘adj’, such that adj[i][j] is a list of two integers [v, w], representing that that ‘jth’ adjacent node of ‘i’ is node ‘v’ and the weight of directed edge i -> v is ‘w’.
- Create a list of integers 'maxDistances' of size 'N' and fill it with -1.
- Create a list ‘order’ of size ‘N’ that will have topological sorting of graph, Topological sorting can be found using this algorithm.
- Assign ‘maxDistances[Src]’ := 0.
- Run a loop where ‘i’ ranges from to ‘N’-1, and for each ‘i’ do following -:
- Initialize an integer variable current := order[i].
- If ‘maxDistances[current] == -1, then continue because this node is not reachable from the source node.
- Visit over all the adjacent nodes 'neighbor’ of node current, and update their distances maxDistances[neighbor] := max( maxDistances[neighbors], maxDistances[current] + weight of directed edge between node at current and neighbor)
- Return ‘maxDistances’.
O(N + E), where ‘N’ is the number of nodes in the given directed graph and E is the number of edges.
The space used by the adjacency list ‘adj’ is of the order of O(N + E) and the space used by array ‘maxDistances’ is of order O(N). Thus, the final space complexity will be O(N+E) + O(N) = O(N+E).
Time Complexity: OtherExplanation:O(N+E), where ‘N’ is the number of nodes in the given directed graph and E is the number of edges.
Topological sorting will take the time of the order of O(N+E), and also we iterate over neighbors of all the nodes which also takes time O(N + E). Thus, the final complexity will be O(N+E) + O(N+E) = O(N+E).
Java (SE 1.8)
/*
Time Complexity : O(N+E)
Space Complexity : O(N+E)
Where 'N' is the number of nodes in the given directed graph
and 'E' is the number of edges.
*/
import java.util.ArrayList;
import java.util.Stack;
public class Solution {
private static void topologicalSortUtil(int current, ArrayList>> adj,
ArrayList visited, Stack stk) {
/*
* Parameters of this function are -: 'current': current node. 'adj': adjacency
* list of given directed graph. 'visited': Booleanean array to track whether
* node is visited or not. 'stk': stack that will keep topological order of
* nodes.
*/
// Mark current node visited
visited.set(current, true);
// Iterating over adjacent vertices.
for (int i = 0; i < adj.get(current).size(); i++) {
if (visited.get(adj.get(current).get(i).get(0)) == false) {
topologicalSortUtil(adj.get(current).get(i).get(0), adj, visited, stk);
}
}
// Push vertex in stack after pushing all its adjacent (and their adjacent and
// so on) verices.
stk.push(current);
}
private static ArrayList topologicalSort(ArrayList>> adj) {
// Number of nodes in a graph.
int n = adj.size();
ArrayList visited = new ArrayList();
for (int i = 0; i < n; i++) {
visited.add(false);
}
Stack stk = new Stack();
// Recursively finding topological sorting.
for (int i = 0; i < n; i++) {
if (!visited.get(i)) {
topologicalSortUtil(i, adj, visited, stk);
}
}
// List 'result' will keep topological sort of given graph.
ArrayList result = new ArrayList();
while (!stk.isEmpty()) {
result.add(stk.peek());
stk.pop();
}
return result;
}
public static ArrayList findMaxDistances(int n, int src, ArrayList> edges) {
// Create Adjacency List.
ArrayList>> adj = new ArrayList>>();
for (int i = 0; i < n; i++) {
adj.add(new ArrayList>());
}
for (int i = 0; i < edges.size(); i++) {
ArrayList temp = new ArrayList();
temp.add(edges.get(i).get(1));
temp.add(edges.get(i).get(2));
adj.get(edges.get(i).get(0)).add(temp);
}
// Find topological sorting.
ArrayList order = topologicalSort(adj);
// Create a list 'maxDistances' of size 'N'and fill it with -1.
ArrayList maxDistances = new ArrayList();
for (int i = 0; i < n; i++) {
maxDistances.add(-1);
}
maxDistances.set(src, 0);
// Find maximum distances of each node from 'Src'.
for (int i = 0; i < n; i++) {
int current = order.get(i);
if (maxDistances.get(current) == -1) {
// Skip this node as it is not reachable from source node.
continue;
}
for (int j = 0; j < adj.get(current).size(); j++) {
int neighbor = adj.get(current).get(j).get(0);
maxDistances.set(neighbor, Math.max(maxDistances.get(neighbor),
maxDistances.get(current) + adj.get(current).get(j).get(1)));
}
}
return maxDistances;
}
}
C++ (g++ 5.4)
/*
Time Complexity : O(N+E)
Space Complexity : O(N+E)
Where ‘N’ is the number of nodes in the given directed graph
and 'E' is the number of edges.
*/
#include
void topologicalSortUtil(int current, vector>> &adj, vector &visited, stack &stk) {
/*
Parameters of this function are -:
'current': current node.
'adj': adjacency list of given directed graph.
'visited': boolean array to track whether node is visited or not.
'stk': stack that will keep topological order of nodes.
*/
// Mark current node visited
visited[current] = true;
// Iterating over adjacent vertices.
for(int i = 0; i < adj[current].size(); i++) {
if(visited[adj[current][i][0]] == false) {
topologicalSortUtil(adj[current][i][0], adj, visited, stk);
}
}
// Push vertex in stack after pushing all its adjacent (and their adjacent and so on) verices.
stk.push(current);
}
vector topologicalSort(vector>> &adj) {
// Number of nodes in a graph.
int n = adj.size();
vector visited(n);
stack stk;
// Recursively finding topological sorting.
for(int i = 0; i < n; i++) {
if(!visited[i]) {
topologicalSortUtil(i, adj, visited, stk);
}
}
// List 'result' will keep topological sort of given graph.
vector result;
while(!stk.empty()) {
result.push_back(stk.top());
stk.pop();
}
return result;
}
vector findMaxDistances(int n, int src, vector> &edges) {
// Create Adjacency List.
vector>> adj(n);
for(int i = 0; i < edges.size(); i++) {
adj[edges[i][0]].push_back(vector({edges[i][1], edges[i][2]}));
}
// Find topological sorting.
vector order = topologicalSort(adj);
// Create a list 'maxDistances' of size 'N' and fill it with negative infinity.
vector maxDistances(n, -1);
maxDistances[src] = 0;
// Find maximum distances of each node from 'Src'.
for(int i = 0; i < n; i++) {
int current = order[i];
if(maxDistances[current] == -1) {
// Skip this node as it is not reachable from source node.
continue;
}
for(int j = 0; j < adj[current].size(); j++) {
int neighbor = adj[current][j][0];
maxDistances[neighbor] = max(maxDistances[neighbor], maxDistances[current] + adj[current][j][1]);
}
}
return maxDistances;
}
Python (3.5)
'''
Time Complexity : O(N+E)
Space Complexity : O(N+E)
Where ‘N’ is the number of nodes in the given directed graph
and 'E' is the number of edges.
'''
def topologicalSortUtil(current, adj, visited, stk):
'''
Parameters of this function are -:
'current': current node.
'adj': adjacency list of given directed graph.
'visited': boolean array to track whether node is visited or not.
'stk': stack that will keep topological order of nodes.
'''
# Mark current node visited
visited[current] = True
# Iterating over adjacent vertices.
for i in range(len(adj[current])):
if(visited[adj[current][i][0]] == False):
topologicalSortUtil(adj[current][i][0], adj, visited, stk)
# Push vertex in stack after pushing all its adjacent (and their adjacent and so on) verices.
stk.append(current)
def topologicalSort(adj):
# Number of nodes in a graph.
n = len(adj)
visited = [False for i in range(n)]
stk = []
# Recursively finding topological sorting.
for i in range(n):
if(visited[i] == False):
topologicalSortUtil(i, adj, visited, stk)
# List 'result' will keep topological sort of given graph.
result = []
while(len(stk) > 0):
result.append(stk[-1])
stk.pop()
return result
def findMaxDistances(n, src, edges):
# Create Adjacency List.
adj = [[] for i in range(n)]
for i in range(len(edges)):
adj[edges[i][0]].append([edges[i][1], edges[i][2]])
# Find topological sorting.
order = topologicalSort(adj)
# Create a list 'maxDistances' of size 'N' and fill it with negative infinity.
maxDistances = [-1 for i in range(n)]
maxDistances[src] = 0
# Find maximum distances of each node from 'Src'.
for i in range(n):
current = order[i]
if(maxDistances[current] == -1):
# Skip this node as it is not reachable from source node.
continue
for j in range(len(adj[current])):
neighbor = adj[current][j][0]
maxDistances[neighbor] = max(
maxDistances[neighbor], maxDistances[current] + adj[current][j][1])
return maxDistances
Top Salesforce Associate Software Engineer interview questions & answers
Popular interview questions of Associate Software Engineer
Reviews
Interviews
Salaries
Users/Month