Skip to content
Related Articles

Related Articles

Improve Article

Longest path in a directed Acyclic graph | Dynamic Programming

  • Difficulty Level : Hard
  • Last Updated : 15 Jun, 2021

Given a directed graph G with N vertices and M edges. The task is to find the length of the longest directed path in Graph.
Note: Length of a directed path is the number of edges in it. 
Examples: 
 

Input: N = 4, M = 5 
 

Output:
The directed path 1->3->2->4 
Input: N = 5, M = 8 
 



Output:

 

Simple Approach: A naive approach is to calculate the length of the longest path from every node using DFS
The time complexity of this approach is O(N2). 
Efficient Approach: An efficient approach is to use Dynamic Programming and DFS together to find the longest path in the Graph. 
Let dp[i] be the length of the longest path starting from the node i. Initially all positions of dp will be 0. We can call the DFS function from every node and traverse for all its children. The recursive formula will be: 
 

dp[node] = max(dp[node], 1 + max(dp[child1], dp[child2], dp[child3]..)) 
 

At the end check for the maximum value in dp[] array, which will be the longest path in the DAG.
Below is the implementation of the above approach:
 

C++




// C++ program to find the longest
// path in the DAG
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to traverse the DAG
// and apply Dynamic Programming
// to find the longest path
void dfs(int node, vector<int> adj[], int dp[], bool vis[])
{
    // Mark as visited
    vis[node] = true;
 
    // Traverse for all its children
    for (int i = 0; i < adj[node].size(); i++) {
 
        // If not visited
        if (!vis[adj[node][i]])
            dfs(adj[node][i], adj, dp, vis);
 
        // Store the max of the paths
        dp[node] = max(dp[node], 1 + dp[adj[node][i]]);
    }
}
 
// Function to add an edge
void addEdge(vector<int> adj[], int u, int v)
{
    adj[u].push_back(v);
}
 
// Function that returns the longest path
int findLongestPath(vector<int> adj[], int n)
{
    // Dp array
    int dp[n + 1];
    memset(dp, 0, sizeof dp);
 
    // Visited array to know if the node
    // has been visited previously or not
    bool vis[n + 1];
    memset(vis, false, sizeof vis);
 
    // Call DFS for every unvisited vertex
    for (int i = 1; i <= n; i++) {
        if (!vis[i])
            dfs(i, adj, dp, vis);
    }
 
    int ans = 0;
 
    // Traverse and find the maximum of all dp[i]
    for (int i = 1; i <= n; i++) {
        ans = max(ans, dp[i]);
    }
    return ans;
}
 
// Driver Code
int main()
{
    int n = 5;
    vector<int> adj[n + 1];
 
    // Example-1
    addEdge(adj, 1, 2);
    addEdge(adj, 1, 3);
    addEdge(adj, 3, 2);
    addEdge(adj, 2, 4);
    addEdge(adj, 3, 4);
 
    cout << findLongestPath(adj, n);
    return 0;
}

Java




// Java program to find the longest
// path in the DAG
 
import java.util.ArrayList;
 
// graph class
class Graph
{
 
    int vertices;
    ArrayList<Integer> edge[];
 
    Graph(int vertices)
    {
        this.vertices = vertices;
        edge = new ArrayList[vertices+1];
        for (int i = 0; i <= vertices; i++)
        {
            edge[i] = new ArrayList<>();
        }
    }
    void addEdge(int a,int b)
    {
        edge[a].add(b);
    }
 
    void dfs(int node, ArrayList<Integer> adj[], int dp[],
                                    boolean visited[])
    {
        // Mark as visited
        visited[node] = true;
 
        // Traverse for all its children
        for (int i = 0; i < adj[node].size(); i++)
        {
 
            // If not visited
            if (!visited[adj[node].get(i)])
                dfs(adj[node].get(i), adj, dp, visited);
 
            // Store the max of the paths
            dp[node] = Math.max(dp[node], 1 + dp[adj[node].get(i)]);
        }
    }
     
    // Function that returns the longest path
    int findLongestPath( int n)
    {
        ArrayList<Integer> adj[] = edge;
        // Dp array
        int[] dp = new int[n+1];
 
        // Visited array to know if the node
        // has been visited previously or not
        boolean[] visited = new boolean[n + 1];
 
        // Call DFS for every unvisited vertex
        for (int i = 1; i <= n; i++)
        {
            if (!visited[i])
                dfs(i, adj, dp, visited);
        }
 
        int ans = 0;
 
        // Traverse and find the maximum of all dp[i]
        for (int i = 1; i <= n; i++)
        {
            ans = Math.max(ans, dp[i]);
        }
        return ans;
    }
}
 
public class Main
{
    // Driver code
    public static void main(String[] args)
    {
        int n = 5;
        Graph graph = new Graph(n);
        // Example-1
        graph.addEdge( 1, 2);
        graph.addEdge( 1, 3);
        graph.addEdge( 3, 2);
        graph.addEdge( 2, 4);
        graph.addEdge( 3, 4);
        graph.findLongestPath(n);
        System.out.println( graph.findLongestPath( n));
 
    }
}
 
// This code is contributed by SumanSaurav

Python3




# Python3 program to find the
# longest path in the DAG
   
# Function to traverse the DAG
# and apply Dynamic Programming
# to find the longest path
def dfs(node, adj, dp, vis):
  
    # Mark as visited
    vis[node] = True
   
    # Traverse for all its children
    for i in range(0, len(adj[node])): 
   
        # If not visited
        if not vis[adj[node][i]]:
            dfs(adj[node][i], adj, dp, vis)
   
        # Store the max of the paths
        dp[node] = max(dp[node], 1 + dp[adj[node][i]])
   
# Function to add an edge
def addEdge(adj, u, v):
  
    adj[u].append(v)
   
# Function that returns the longest path
def findLongestPath(adj, n):
  
    # Dp array
    dp = [0] * (n + 1)
     
    # Visited array to know if the node
    # has been visited previously or not
    vis = [False] * (n + 1)
     
    # Call DFS for every unvisited vertex
    for i in range(1, n + 1): 
        if not vis[i]:
            dfs(i, adj, dp, vis)
      
    ans = 0
   
    # Traverse and find the maximum of all dp[i]
    for i in range(1, n + 1): 
        ans = max(ans, dp[i])
      
    return ans
  
# Driver Code
if __name__ == "__main__":
  
    n = 5
    adj = [[] for i in range(n + 1)]
   
    # Example-1
    addEdge(adj, 1, 2)
    addEdge(adj, 1, 3)
    addEdge(adj, 3, 2)
    addEdge(adj, 2, 4)
    addEdge(adj, 3, 4)
   
    print(findLongestPath(adj, n))
   
# This code is contributed by Rituraj Jain

C#




// C# program to find the longest
// path in the DAG
using System;
using System.Collections.Generic;
 
// graph class
class Graph
{
    public int vertices;
    public List<int> []edge;
 
    public Graph(int vertices)
    {
        this.vertices = vertices;
        edge = new List<int>[vertices + 1];
        for (int i = 0; i <= vertices; i++)
        {
            edge[i] = new List<int>();
        }
    }
    public void addEdge(int a, int b)
    {
        edge[a].Add(b);
    }
 
    public void dfs(int node, List<int> []adj,
                    int []dp, Boolean []visited)
    {
        // Mark as visited
        visited[node] = true;
 
        // Traverse for all its children
        for (int i = 0; i < adj[node].Count; i++)
        {
 
            // If not visited
            if (!visited[adj[node][i]])
                dfs(adj[node][i], adj, dp, visited);
 
            // Store the max of the paths
            dp[node] = Math.Max(dp[node], 1 +
                                dp[adj[node][i]]);
        }
    }
     
    // Function that returns the longest path
    public int findLongestPath( int n)
    {
        List<int> []adj = edge;
        // Dp array
        int[] dp = new int[n + 1];
 
        // Visited array to know if the node
        // has been visited previously or not
        Boolean[] visited = new Boolean[n + 1];
 
        // Call DFS for every unvisited vertex
        for (int i = 1; i <= n; i++)
        {
            if (!visited[i])
                dfs(i, adj, dp, visited);
        }
 
        int ans = 0;
 
        // Traverse and find the maximum of all dp[i]
        for (int i = 1; i <= n; i++)
        {
            ans = Math.Max(ans, dp[i]);
        }
        return ans;
    }
}
 
class GFG
{
    // Driver code
    public static void Main(String[] args)
    {
        int n = 5;
        Graph graph = new Graph(n);
        // Example-1
        graph.addEdge( 1, 2);
        graph.addEdge( 1, 3);
        graph.addEdge( 3, 2);
        graph.addEdge( 2, 4);
        graph.addEdge( 3, 4);
        graph.findLongestPath(n);
        Console.WriteLine(graph.findLongestPath(n));
    }
}
 
// This code is contributed by Princi Singh

Javascript




<script>
 
// JavaScript program to find the longest
// path in the DAG
 
// Function to traverse the DAG
// and apply Dynamic Programming
// to find the longest path
function dfs(node, adj, dp, vis)
{
    // Mark as visited
    vis[node] = true;
 
    // Traverse for all its children
    for (var i = 0; i < adj[node].length; i++) {
 
        // If not visited
        if (!vis[adj[node][i]])
            dfs(adj[node][i], adj, dp, vis);
 
        // Store the max of the paths
        dp[node] = Math.max(dp[node], 1 + dp[adj[node][i]]);
    }
}
 
// Function to add an edge
function addEdge(adj, u, v)
{
    adj[u].push(v);
}
 
// Function that returns the longest path
function findLongestPath(adj, n)
{
    // Dp array
    var dp = Array(n+1).fill(0);
 
    // Visited array to know if the node
    // has been visited previously or not
    var vis = Array(n+1).fill(false);
 
    // Call DFS for every unvisited vertex
    for (var i = 1; i <= n; i++) {
        if (!vis[i])
            dfs(i, adj, dp, vis);
    }
 
    var ans = 0;
 
    // Traverse and find the maximum of all dp[i]
    for (var i = 1; i <= n; i++) {
        ans = Math.max(ans, dp[i]);
    }
    return ans;
}
 
// Driver Code
var n = 5;
var adj = Array.from(Array(n+1), ()=>Array());
// Example-1
addEdge(adj, 1, 2);
addEdge(adj, 1, 3);
addEdge(adj, 3, 2);
addEdge(adj, 2, 4);
addEdge(adj, 3, 4);
document.write( findLongestPath(adj, n));
 
</script>
Output: 
3

 

Time Complexity: O(N) 
Auxiliary Space: O(N) 
 

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up