最大化给定根树中节点对之间的差异,使得一个节点是另一个节点的祖先
给定一个由N个节点组成的通用树,其值从0到(N – 1) ,其中数组P[]中的第 P[i ]个节点表示第 i个节点的父节点(基于 1 的索引) 。每个第 i个节点都附加一个权重,在数组W[]中给出。任务是找到一对节点(u, v),使得u是v的祖先,并且W u - W v被最大化。
注意:在数组P[]中, -1表示根节点。如果只有一个节点,则打印-1 。
例子:
Input: N = 4, W[] = {5, 10, 6, 12}, P[] = {2, -1, 4, 2}
Output: 6
Explanation: The tree with weight will be:
Here, 4th node having weight 12 and 3rd node having weight 6, the difference will be (12 – 6) = 6.
Input: N = 1, W = { 30 }, P = { -1 }
Output: -1
方法:给定问题可以通过在N-ary Tree上使用广度优先搜索来标记给定树P[]的祖先编号,然后使用 DFS Traversal 并通过考虑每个节点找到最大差异maxDiff来解决给定问题作为一个祖先,其对应的节点具有较少的祖先值。请按照以下步骤解决问题:
- 定义一个函数dfs(int src, int val, vector
& W) 并执行以下任务:- 将visited[src]的值设置为true 。
- 使用变量邻居迭代范围[0, size) ,其中size是行树 [cur]的大小,并执行以下任务:
- 如果visited[neighbor]为假并且祖先[neighbor]大于祖先[src] ,则将maxDiff的值设置为maxDiff或val – W[neighbor-1]的最大值。
- 调用函数dfs(neighbor, val, W) 。
- 定义一个函数bfs(int src, int N)并执行以下任务:
- 将向量visited[N + 1]赋值为false。
- 初始化队列q[] 。
- 将ansectorNum[src]的值设置为0 ,并将visited[src]的值设置为true 。
- 将值src排入队列q[] 。
- 在while循环中遍历直到队列q[]不为空并执行以下任务:
- 将变量cur初始化为队列q[]的前端元素并从队列q[] 中出列。
- 迭代范围[0, size) ,其中size是使用变量neighbor的行树 [cur]的大小,如果visited[neighbor]为false ,则将其设置为true并将其排入队列q[]并设置祖先[neighbor]的值为(ancestor[cur] + 1) 。
- 初始化向量tree[][]、visited[]和祖先Num[] 。
- 将变量maxDiff初始化为INT_MIN以存储答案。
- 将向量tree[][]的大小调整为(N + 1) 。
- 将向量visited[N + 1]赋值为false ,并将祖先Num[N+1]赋值为0 。
- 初始化变量src 。
- 使用变量i遍历范围[0, N) ,如果P[ I ]为-1 ,则将src的值设置为i 。否则,将行i+1中的值P[ I ]和行P [ I ]中的值i + 1推入向量树[][] 。
- 调用函数bfs(src, N+1)进行广度优先搜索。
- 将向量visited[N+1]赋值为false 。
- 调用函数dfs(src, W[src], W)执行深度优先搜索。
- 使用变量i迭代范围[0, N)并执行以下步骤:
- 如果i等于src ,则继续。否则,将向量visited[N+1]赋值为false 。
- 调用函数dfs(i+1, W[i], W) 。
- 执行上述步骤后,打印maxDiff的值作为答案。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
vector > tree;
vector visited;
vector ancestorNum;
// Stores the maximum difference
int maxDiff = INT_MIN;
// DFS traversal for source node as src
void dfs(int src, int val, vector& W)
{
// Mark src node as visited
visited[src] = true;
// Traverse the tree
for (auto neighbour : tree[src]) {
// Check neighbour node is not
// visited and ancestorNum should
// be greater than the src node
if (!visited[neighbour]
&& (ancestorNum[neighbour]
> ancestorNum[src])) {
// Update the maxDiff
maxDiff = max(
val - W[neighbour - 1],
maxDiff);
// Recurrence call for dfs
dfs(neighbour, val, W);
}
}
}
// BFS traversal for source node as src
void bfs(int src, int N)
{
// Initially mark all node as
// not visited
visited.assign(N, false);
// Stores the nodes
queue q;
// Initially for src node mark
// ancestorNum as 0
ancestorNum[src] = 0;
// Mark src as visited
visited[src] = true;
// Push src node into the q
q.push(src);
// Traverse the queue q
while (!q.empty()) {
// Pop front element of the q
int cur = q.front();
q.pop();
// Traverse the tree
for (auto neighbour : tree[cur]) {
// Check neighbour node is
// already not visited
if (!visited[neighbour]) {
// Mark the neighbour
// node as visited
visited[neighbour] = true;
// Push the neighbour
// node into the q
q.push(neighbour);
// Update the neighbour
// node ancestorNum
ancestorNum[neighbour]
= ancestorNum[cur] + 1;
}
}
}
}
// Function to find the the maximized
// difference between two pair of nodes
// in rooted tree such that one node
// is ancestor of another node
void maximumDiff(vector W,
vector P, int N)
{
if (N == 1) {
cout << "-1\n";
return;
}
// Resize the tree
tree.resize(N + 1);
// Mark all the nodes as not visited
visited.assign(N + 1, false);
// Assign all the node values
// for ancestorNum to 0
ancestorNum.assign(N + 1, 0);
// Stores the source node to traverse
int src;
for (int i = 0; i < N; i++) {
// Check P[i] is -1
if (P[i] == -1)
// Update the source node src
src = i;
else {
// Store the tree values
tree[i + 1].push_back(P[i]);
tree[P[i]].push_back(i + 1);
}
}
// BFS from the source node src
bfs(src, N + 1);
// Mark all the nodes as not visited
visited.assign(N + 1, false);
// DFS Call for source node src
dfs(src, W[src], W);
// For every node call dfs function
for (int i = 0; i < N; i++) {
// Check i is root node
if (i == src)
continue;
// Mark all the nodes as
// not visited
visited.assign(N + 1, false);
// DFS Call for source
// node as i+1
dfs(i + 1, W[i], W);
}
// Print the maxDiff
cout << maxDiff << endl;
}
// Driver Code
int main()
{
vector W = { 5, 10, 6, 12 };
vector P = { 2, -1, 4, 2 };
int N = P.size();
maximumDiff(W, P, N);
return 0;
}
Python3
# Python 3 program for the above approach
tree = []
visited = []
ancestorNum = []
import sys
# Stores the maximum difference
maxDiff = -sys.maxsize - 1
# DFS traversal for source node as src
def dfs(src, val, W):
global ancestorNum
global visited
global tree
global maxDiff
# Mark src node as visited
visited[src] = True
# Traverse the tree
for neighbour in tree[src]:
# Check neighbour node is not
# visited and ancestorNum should
# be greater than the src node
if (visited[neighbour] == False and (ancestorNum[neighbour]> ancestorNum[src])):
# Update the maxDiff
maxDiff = max(val - W[neighbour - 1],maxDiff)
# Recurrence call for dfs
dfs(neighbour, val, W)
# BFS traversal for source node as src
def bfs(src,N):
global ancestorNum
global visited
global tree
# Initially mark all node as
# not visited
visited = [False for i in range(N)]
# Stores the nodes
q = []
# Initially for src node mark
# ancestorNum as 0
ancestorNum[src] = 0
# Mark src as visited
visited[src] = True
# Push src node into the q
q.append(src)
# Traverse the queue q
while (len(q)>0):
# Pop front element of the q
cur = q[0]
q = q[1:]
# Traverse the tree
for neighbour in tree[cur]:
# Check neighbour node is
# already not visited
if (visited[neighbour]==False):
# Mark the neighbour
# node as visited
visited[neighbour] = True
# Push the neighbour
# node into the q
q.append(neighbour)
# Update the neighbour
# node ancestorNum
ancestorNum[neighbour] = ancestorNum[cur] + 1
# Function to find the the maximized
# difference between two pair of nodes
# in rooted tree such that one node
# is ancestor of another node
def maximumDiff(W, P, N):
global ancestorNum
global visited
global tree
if (N == 1):
print("-1")
return
# Resize the tree
tree = [[] for i in range(N+1)]
# Mark all the nodes as not visited
visited = [False for i in range(N + 1)]
# Assign all the node values
# for ancestorNum to 0
ancestorNum = [0 for i in range(N + 1)]
# Stores the source node to traverse
src = 0
for i in range(N):
# Check P[i] is -1
if (P[i] == -1):
# Update the source node src
src = i
else:
# Store the tree values
tree[i + 1].append(P[i])
tree[P[i]].append(i + 1)
# BFS from the source node src
bfs(src, N + 1)
# Mark all the nodes as not visited
visited = [False for i in range(N+1)]
# DFS Call for source node src
dfs(src, W[src], W)
# For every node call dfs function
for i in range(N):
# Check i is root node
if (i == src):
continue
# Mark all the nodes as
# not visited
visited = [False for i in range(N+1)]
# DFS Call for source
# node as i+1
dfs(i + 1, W[i], W)
# Print the maxDiff
print(maxDiff)
# Driver Code
if __name__ == '__main__':
W = [5, 10, 6, 12]
P = [2, -1, 4, 2]
N = len(P)
maximumDiff(W, P, N)
# This code is contributed by SURENDRA_GANGWAR.
输出:
6
时间复杂度: O(N 2 )
辅助空间: O(N)