Skip to content
Related Articles

Related Articles

Save Article
Improve Article
Save Article
Like Article

Maximize difference between pair of nodes in a given rooted tree such that one node is ancestor of another

  • Last Updated : 21 Sep, 2021

Given a Generic Tree consisting of N nodes valued from 0 to (N – 1) where P[i]th in the array P[] denotes ith nodes parent(1-based indexing). Each ith node has a weight attached to it, given in the array W[]. The task is to find a pair of nodes (u, v), such that u is an ancestor of v, and Wu – Wv is maximized.

Note: In the array P[], -1 denotes the root node. If there’s a single node, then print -1.

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.

Examples:



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

 

Approach: The given problem can be solved by using the Breadth-First Search on the N-ary Tree to mark the ancestor number for the given tree P[], and then using DFS Traversal and find the maximum difference maxDiff, by considering every node as an ancestor with its corresponding nodes having less number ancestor value. Follow the steps below to solve the problem:

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
vector<vector<int> > tree;
vector<bool> visited;
vector<int> ancestorNum;
 
// Stores the maximum difference
int maxDiff = INT_MIN;
 
// DFS traversal for source node as src
void dfs(int src, int val, vector<int>& 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<int> 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<int> W,
                 vector<int> 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<int> W = { 5, 10, 6, 12 };
    vector<int> 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.
Output: 
6

 

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

 




My Personal Notes arrow_drop_up
Recommended Articles
Page :