Open In App

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

Last Updated : 13 Feb, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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.

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 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;
}


Java




// Java program for the above approach
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
 
public class Main {
    private static ArrayList<ArrayList<Integer> > tree;
    private static boolean[] visited;
    private static int[] ancestorNum;
    private static int maxDiff = Integer.MIN_VALUE;
    private static void dfs(int src, int val, int[] W)
    {
        visited[src] = true;
        // Check neighbour node is not
        // visited and ancestorNum should
        // be greater than the src node
        for (int neighbour : tree.get(src)) {
            if (!visited[neighbour]
                && ancestorNum[neighbour]
                       > ancestorNum[src]) {
                maxDiff = Math.max(val - W[neighbour - 1],
                                   maxDiff);
                dfs(neighbour, val, W);
            }
        }
    }
 
    private static void bfs(int src, int N)
    {
        visited = new boolean[N];
        Arrays.fill(visited, false);
        Queue<Integer> q = new LinkedList<>();
        ancestorNum[src] = 0;
        visited[src] = true;
        q.offer(src);
        while (!q.isEmpty()) {
            int cur = q.poll();
            for (int neighbour : tree.get(cur)) {
                if (!visited[neighbour]) {
                    visited[neighbour] = true;
                    q.offer(neighbour);
                    ancestorNum[neighbour]
                        = ancestorNum[cur] + 1;
                }
            }
        }
    }
    // Function to find the maximized
    // difference between two pair of nodes
    // in rooted tree such that one node
    // is ancestor of another node
    private static void maximumDiff(int[] W, int[] P, int N)
    {
        if (N == 1) {
            System.out.println("-1");
            return;
        }
 
        tree = new ArrayList<>();
        for (int i = 0; i <= N; i++)
            tree.add(new ArrayList<>());
 
        int src = 0;
        for (int i = 0; i < N; i++) {
            if (P[i] == -1) {
                src = i;
            }
            else {
                tree.get(i + 1).add(P[i]);
                tree.get(P[i]).add(i + 1);
            }
        }
        // Assign all the node values
        // for ancestorNum to 0
        ancestorNum = new int[N + 1];
        bfs(src, N + 1);
 
        Arrays.fill(visited, false);
        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;
            Arrays.fill(visited, false);
            dfs(i + 1, W[i], W);
        }
 
        System.out.println(maxDiff);
    }
 
    public static void main(String[] args)
    {
        int[] W = { 5, 10, 6, 12 };
        int[] P = { 2, -1, 4, 2 };
        int N = P.length;
 
        maximumDiff(W, P, N);
    }
}


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 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.


C#




// C# program for the above approach
using System;
using System.Collections.Generic;
 
// Stores the maximum difference
class Program
{
 
  // Stores the maximum difference
  static int maxDiff = int.MinValue;
  static List<List<int>> tree = new List<List<int>>();
  static bool[] visited;
  static int[] ancestorNum;
 
  // DFS traversal for source node as src
  static void DFS(int src, int val, int[] W)
  {
 
    // Mark src node as visited
    visited[src] = true;
 
    // Traverse the tree
    foreach (int neighbour in 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 = Math.Max(val - W[neighbour - 1], maxDiff);
 
        // Recurrence call for dfs
        DFS(neighbour, val, W);
      }
    }
  }
 
  // BFS traversal for source node as src
  static void BFS(int src, int N)
  {
 
    // Initially mark all node as
    // not visited
    visited = new bool[N];
 
    // Initially for src node mark
    // ancestorNum as 0
    Queue<int> q = new Queue<int>();
 
    ancestorNum = new int[N];
    ancestorNum[src] = 0;
    visited[src] = true;
    q.Enqueue(src);
 
    while (q.Count > 0)
    {
      int cur = q.Dequeue();
      foreach (int neighbour in tree[cur])
      {
        if (!visited[neighbour])
        {
          visited[neighbour] = true;
          q.Enqueue(neighbour);
          ancestorNum[neighbour] = ancestorNum[cur] + 1;
        }
      }
    }
  }
 
  static void MaximumDiff(int[] W, int[] P, int N)
  {
    if (N == 1)
    {
      Console.WriteLine("-1");
      return;
    }
 
    tree = new List<List<int>>();
    for (int i = 0; i <= N; i++)
    {
      tree.Add(new List<int>());
    }
 
    int src = 0;
    for (int i = 0; i < N; i++)
    {
      if (P[i] == -1)
      {
        src = i;
      }
      else
      {
        tree[i + 1].Add(P[i]);
        tree[P[i]].Add(i + 1);
      }
    }
 
    BFS(src, N + 1);
    visited = new bool[N + 1];
    DFS(src, W[src], W);
 
    for (int i = 0; i < N; i++)
    {
      if (i == src)
        continue;
 
      visited = new bool[N + 1];
      DFS(i + 1, W[i], W);
    }
 
    Console.WriteLine(maxDiff);
  }
 
  // Driver Code
  static void Main(string[] args)
  {
    int[] W = { 5, 10, 6, 12 };
    int[] P = { 2, -1, 4, 2 };
    int N = P.Length;
 
    MaximumDiff(W, P, N);
  }
}


Javascript




       // JavaScript code for the above approach
       let tree = [];
       let visited = [];
       let ancestorNum = [];
 
       // Stores the maximum difference
       let maxDiff = Number.MIN_SAFE_INTEGER;
 
       // DFS traversal for source node as src
       function dfs(src, val, W)
       {
        
           // Mark src node as visited
           visited[src] = true;
 
           // Traverse the tree
           for (let neighbour of 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 = Math.max(val - W[neighbour - 1], maxDiff,6);
 
                   // Recurrence call for dfs
                   dfs(neighbour, val, W);
               }
           }
       }
 
       // BFS traversal for source node as src
       function bfs(src, N) {
           // Initially mark all node as
           // not visited
           visited = Array(N).fill(false);
 
           // Stores the nodes
           let 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.length > 0)
           {
            
               // Pop front element of the q
               let cur = q.shift();
 
               // Traverse the tree
               for (let neighbour of 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 maximized
       // difference between two pair of nodes
       // in rooted tree such that one node
       // is ancestor of another node
       function maximumDiff(W, P, N) {
           if (N === 1) {
               console.log("-1");
               return;
           }
 
           // Resize the tree
           tree= new Array(N + 1);
           tree.fill([]);
 
           // Mark all the nodes as not visited
           visited = Array(N + 1).fill(false);
 
           // Assign all the node values
           // for ancestorNum to 0
           ancestorNum.length = N + 1;
           ancestorNum.fill(0);
 
           // Stores the source node to traverse
           let src = 0;
 
           for (let i = 0; i < N; i += 1) {
               // 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(P[i]);
                   tree[P[i]].push(i + 1);
               }
           }
 
           // BFS from the source node src
           bfs(src, N + 1);
 
           // Mark all the nodes as not visited
           visited = Array(N + 1).fill(false);
 
           // DFS Call for source node src
           dfs(src, W[src], W);
 
           // For every node call dfs function
           for (let i = 0; i < N; i += 1) {
               // Check i is root node
               if (i === src) continue;
 
               // Mark all the nodes as
               // not visited
               visited = Array(N + 1).fill(false);
 
               // DFS Call for source
               // node as i+1
               dfs(i + 1, W[i], W);
           }
 
           // Print the maxDiff
           console.log(maxDiff);
       }
 
       // Test the code
       maximumDiff([5, 10, 6, 12], [2, -1, 4, 2], 4);
 
// This code is contributed by Potta Lokesh


Output: 

6

 

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

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads