📜  有向无环图中的最长路径|动态规划

📅  最后修改于: 2021-09-17 07:25:27             🧑  作者: Mango

给定一个有N 个顶点M 个边的有向图G。任务是找到Graph中最长有向路径的长度。
注意:有向路径的长度是其中的边数。
例子:

简单的方法:一种简单的方法是使用 DFS 计算每个节点的最长路径的长度。
这种方法的时间复杂度是 O(N 2 )。
有效的方法:一种有效的方法是结合使用动态规划和 DFS 来找到图中的最长路径。
dp[i]是从节点i开始的最长路径的长度。最初 dp 的所有位置都将为 0。我们可以从每个节点调用 DFS函数并遍历其所有子节点。递归公式将是:

最后检查 dp[] 数组中的最大值,这将是 DAG 中最长的路径。
下面是上述方法的实现:

C++
// C++ program to find the longest
// path in the DAG
 
#include 
using namespace std;
 
// Function to traverse the DAG
// and apply Dynamic Programming
// to find the longest path
void dfs(int node, vector 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 adj[], int u, int v)
{
    adj[u].push_back(v);
}
 
// Function that returns the longest path
int findLongestPath(vector 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 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 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 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 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 []edge;
 
    public Graph(int vertices)
    {
        this.vertices = vertices;
        edge = new List[vertices + 1];
        for (int i = 0; i <= vertices; i++)
        {
            edge[i] = new List();
        }
    }
    public void addEdge(int a, int b)
    {
        edge[a].Add(b);
    }
 
    public void dfs(int node, List []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 []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


输出:
3

时间复杂度: O(N)
辅助空间: O(N)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程