📜  DP 树 | Set-3(N 叉树的直径)

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

给定一棵由 N 个节点组成的 N 叉树 T,任务是计算任意两个节点之间的最长路径(也称为树的直径)。
示例 1:

示例 2:

已经讨论了解决这些问题的不同方法:

  • https://www.geeksforgeeks.org/diameter-n-ary-tree/
  • https://www.geeksforgeeks.org/diameter-n-ary-tree-using-bfs/

在这篇文章中,我们将讨论一种在树上使用动态规划的方法。
先决条件

  • DP 树 |设置 1
  • DP 树 | 2套

直径存在的可能性有两种:

  • 情况 1 :假设直径从一个节点开始,并在其子树中的某个节点结束。假设存在一个节点x使得最长路径从节点x开始并进入其子树,并在子树本身的某个节点处结束。让我们通过 dp1[x]定义这个路径长度。
  • 情况 2 :假设直径或最长路径从节点x 的子树开始,通过它并在它的子树中结束。让我们通过dp2[x]定义这个路径。

如果对于所有节点 x,我们取最大值 dp1[x], dp2[x],那么我们将得到树的直径。
对于 case-1 ,要找到 dp1[node],我们需要找到所有 dp1[x] 的最大值,其中 x 是节点的孩子。 dp1[node] 将等于1 + max(dp1[children1], dp1[children2], ..)
对于 case-2 ,要找到 dp2[node],我们需要找到所有 dp1[x] 的两个最大值,其中 x 是节点的孩子。并且 dp2[node] 将等于1 + max 2 of(dp1[children1], dp1[children2], ..)
我们可以轻松地运行 DFS 并找到 dp1[node] 和 dp2[node] 的最大值,以获得树的直径。
下面是上述方法的实现:

C++
// C++ program to find diameter of a tree
// using DFS.
#include 
using namespace std;
 
int diameter = -1;
 
// Function to find the diameter of the tree
// using Dynamic Programming
int dfs(int node, int parent, int dp1[], int dp2[], list* adj)
{
 
    // Store the first maximum and secondmax
    int firstmax = -1;
    int secondmax = -1;
 
    // Traverse for all children of node
    for (auto i = adj[node].begin(); i != adj[node].end(); ++i) {
        if (*i == parent)
            continue;
 
        // Call DFS function again
        dfs(*i, node, dp1, dp2, adj);
 
        // Find first max
        if (firstmax == -1) {
            firstmax = dp1[*i];
        }
        else if (dp1[*i] >= firstmax) // Secondmaximum
        {
            secondmax = firstmax;
            firstmax = dp1[*i];
        }
        else if (dp1[*i] > secondmax) // Find secondmaximum
        {
            secondmax = dp1[*i];
        }
    }
 
    // Base case for every node
    dp1[node] = 1;
    if (firstmax != -1) // Add
        dp1[node] += firstmax;
 
    // Find dp[2]
    if (secondmax != -1)
        dp2[node] = 1 + firstmax + secondmax;
 
    // Return maximum of both
    return max(dp1[node], dp2[node]);
}
 
// Driver Code
int main()
{
    int n = 5;
 
    /* Constructed tree is
         1
        / \
        2 3
       / \
       4  5 */
    list* adj = new list[n + 1];
 
    /*create undirected edges */
    adj[1].push_back(2);
    adj[2].push_back(1);
    adj[1].push_back(3);
    adj[3].push_back(1);
    adj[2].push_back(4);
    adj[4].push_back(2);
    adj[2].push_back(5);
    adj[5].push_back(2);
 
    int dp1[n + 1], dp2[n + 1];
    memset(dp1, 0, sizeof dp1);
    memset(dp2, 0, sizeof dp2);
 
    // Find diameter by calling function
    cout << "Diameter of the given tree is "
         << dfs(1, 1, dp1, dp2, adj) << endl;
 
    return 0;
}


Python3
# Python3 program to find diameter
# of a tree using DFS.
 
# Function to find the diameter of the
# tree using Dynamic Programming
def dfs(node, parent, dp1, dp2, adj):
 
    # Store the first maximum and secondmax
    firstmax, secondmax = -1, -1
 
    # Traverse for all children of node
    for i in adj[node]:
        if i == parent:
            continue
 
        # Call DFS function again
        dfs(i, node, dp1, dp2, adj)
 
        # Find first max
        if firstmax == -1:
            firstmax = dp1[i]
         
        elif dp1[i] >= firstmax: # Secondmaximum
            secondmax = firstmax
            firstmax = dp1[i]
         
        elif dp1[i] > secondmax: # Find secondmaximum
            secondmax = dp1[i]
 
    # Base case for every node
    dp1[node] = 1
    if firstmax != -1: # Add
        dp1[node] += firstmax
 
    # Find dp[2]
    if secondmax != -1:
        dp2[node] = 1 + firstmax + secondmax
 
    # Return maximum of both
    return max(dp1[node], dp2[node])
 
# Driver Code
if __name__ == "__main__":
 
    n, diameter = 5, -1
 
    adj = [[] for i in range(n + 1)]
     
    # create undirected edges
    adj[1].append(2)
    adj[2].append(1)
    adj[1].append(3)
    adj[3].append(1)
    adj[2].append(4)
    adj[4].append(2)
    adj[2].append(5)
    adj[5].append(2)
 
    dp1 = [0] * (n + 1)
    dp2 = [0] * (n + 1)
     
    # Find diameter by calling function
    print("Diameter of the given tree is",
                 dfs(1, 1, dp1, dp2, adj))
 
# This code is contributed by Rituraj Jain


Javascript


输出:
Diameter of the given tree is 4

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