给定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]的最大值,那么我们将得到树的直径。
对于情况1 ,要找到dp1 [node],我们需要找到所有dp1 [x]的最大值,其中x是node的子代。并且dp1 [node]等于1 + max(dp1 [children1],dp1 [children2],..) 。
对于情况2 ,要找到dp2 [node],我们需要找到所有dp1 [x]的两个最大值,其中x是node的子代。并且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
输出:
Diameter of the given tree is 4