 Open in App
Not now

# Query to find the maximum and minimum weight between two nodes in the given tree using LCA.

• Difficulty Level : Hard
• Last Updated : 23 Jan, 2023

Given a tree, and the weights of all the node. Each query contains two integers u and v, the task is to find the minimum and maximum weight on the simple path between u and v (both inclusive).

Examples:

Input: Query=[{1, 3}, {2, 4}, {3, 5}]
Output:
-1 5
3 5
-2 5
Explanation:
Weight on path 1 to 3 is [-1, 5, -1]. Hence, the minimum and maximum weight is -1 and 5 respectively.
Weight on path 2 to 4 is [5, 3]. Hence, the minimum and maximum weight is 3 and 5 respectively.
Weight on path 2 to 4 is [-1, 5, -1, -2]. Hence, the minimum and maximum weight is -2 and 5 respectively.

Approach: The idea is to use LCA in a tree using Binary Lifting Technique.

• Binary Lifting is a Dynamic Programming approach where we pre-compute an array lca[i][j] where i = [1, n], j = [1, log(n)] and lca[i][j] contains 2j-th ancestor of node i.
• For computing the values of lca[][], the following recursion may be used

lca[i][j] = parent[i] if j = 0 and
lca[i][j] = lca[lca[i][j – 1]][j – 1] if j > 0.

• As we will compute the lca[][] array we will also calculate the MinWeight[][] and MaxWeight[][] where MinWeight[i][j] contains the minimum weight from node i to its 2j-th ancestor, and MaxWeight[i][j] contains the maximum weight from node i to its 2j-th ancestor
• For computing the values of MinWeight[][] and MaxWeight[], the following recursion may be used. [Tex]MaxWeight[i][j] =\begin{cases} max (weight[i], weight[parent[i]]) & \text{ ;if } j=0 \\ max( MaxWeight[i][j-1], MaxWeight[lca[i][j – 1]][j – 1]) & \text{ ;if } j>0 \end{cases} [/Tex]

• After precomputation we find the minimum and maximum weight between (u, v) as we find the least common ancestor of (u, v).

Below is the implementation of the above approach:

## C++

 // C++ Program to find the maximum and // minimum weight between two nodes // in the given tree using LCA   #include  using namespace std;   #define MAX 1000   #define log 10 // log2(MAX)   // Array to store the level // of each node int level[MAX];   int lca[MAX][log]; int minWeight[MAX][log]; int maxWeight[MAX][log];   // Vector to store tree vector<int> graph[MAX]; // Array to store weight of nodes int weight[MAX];   void addEdge(int u, int v) {     graph[u].push_back(v);     graph[v].push_back(u); }   // Pre-Processing to calculate // values of lca[][], MinWeight[][] // and MaxWeight[][] void dfs(int node, int parent, int h) {     // Using recursion formula to     // calculate the values     // of lca[][]     lca[node] = parent;       // Storing the level of     // each node     level[node] = h;     if (parent != -1)      {         minWeight[node]             = min(weight[node], weight[parent]);         maxWeight[node]             = max(weight[node], weight[parent]);     }       for (int i = 1; i < log; i++)      {         if (lca[node][i - 1] != -1)          {               // Using recursion formula to             // calculate the values of lca[][],             // MinWeight[][] and MaxWeight[][]             lca[node][i] = lca[lca[node][i - 1]][i - 1];             minWeight[node][i]                 = min(minWeight[node][i - 1],                       minWeight[lca[node][i - 1]][i - 1]);             maxWeight[node][i]                 = max(maxWeight[node][i - 1],                       maxWeight[lca[node][i - 1]][i - 1]);         }     }       for (int i : graph[node])      {         if (i == parent)             continue;         dfs(i, node, h + 1);     } }   // Function to find the minimum and // maximum weights in the given range void findMinMaxWeight(int u, int v) {       int minWei = INT_MAX;     int maxWei = INT_MIN;       // The node which is present     // farthest from the root node     // is taken as v If u is     // farther from root node     // then swap the two     if (level[u] > level[v])         swap(u, v);       // Finding the ancestor of v     // which is at same level as u     for (int i = log - 1; i >= 0; i--)      {           if (lca[v][i] != -1             && level[lca[v][i]] >= level[u])          {               // Calculating Minimum and             // Maximum Weight of node             // v till its 2^i-th ancestor             minWei = min(minWei, minWeight[v][i]);             maxWei = max(maxWei, maxWeight[v][i]);             v = lca[v][i];         }     }       // If u is the ancestor of v     // then u is the LCA of u and v     if (v == u)      {         cout << minWei << " " << maxWei << endl;     }       else {           // Finding the node closest to the         // root which is not the common         // ancestor of u and v i.e. a node         // x such that x is not the common         // ancestor of u and v but lca[x] is         for (int i = log - 1; i >= 0; i--)          {               if (lca[v][i] != lca[u][i])              {                   // Calculating the minimum of                 // MinWeight of v to its 2^i-th                 // ancestor and MinWeight of u                 // to its 2^i-th ancestor                 minWei = min(minWei, min(minWeight[v][i],                                          minWeight[u][i]));                   // Calculating the maximum of                 // MaxWeight of v to its 2^i-th                 // ancestor and MaxWeight of u                 // to its 2^i-th ancestor                 maxWei = max(maxWei, max(maxWeight[v][i],                                          maxWeight[u][i]));                   v = lca[v][i];                 u = lca[u][i];             }         }           // Calculating the Minimum of         // first ancestor of u and v         minWei = min(minWei,                      min(minWeight[v], minWeight[u]));           // Calculating the maximum of         // first ancestor of u and v         maxWei = max(maxWei,                      max(maxWeight[v], maxWeight[u]));           cout << minWei << " " << maxWei << endl;     } }   // Driver Code int main() {       // Number of nodes     int n = 5;       // Add edges     addEdge(1, 2);     addEdge(1, 5);     addEdge(2, 4);     addEdge(2, 3);       weight = -1;     weight = 5;     weight = -1;     weight = 3;     weight = -2;       // Initialising lca values with -1     // Initialising MinWeight values     // with INT_MAX     // Initialising MaxWeight values     // with INT_MIN     for (int i = 1; i <= n; i++) {         for (int j = 0; j < log; j++) {             lca[i][j] = -1;             minWeight[i][j] = INT_MAX;             maxWeight[i][j] = INT_MIN;         }     }       // Perform DFS     dfs(1, -1, 0);       // Query 1: {1, 3}     findMinMaxWeight(1, 3);       // Query 2: {2, 4}     findMinMaxWeight(2, 4);       // Query 3: {3, 5}     findMinMaxWeight(3, 5);       return 0; }

## Java

 // Java Program to find the maximum and // minimum weight between two nodes // in the given tree using LCA import java.util.*; class GFG{   static final int MAX = 1000;   // Math.log(MAX) static final int log = 10 ;   // Array to store the  // level of each node static int []level =         new int[MAX];   static int [][]lca =         new int[MAX][log]; static int [][]minWeight =         new int[MAX][log]; static int [][]maxWeight =         new int[MAX][log];   // Vector to store tree static Vector []graph =                new Vector[MAX];     // Array to store // weight of nodes static int []weight =         new int[MAX];     private static void swap(int x,                           int y)  {   int temp = x;   x = y;   y = temp; }   static void addEdge(int u,                      int v) {   graph[u].add(v);   graph[v].add(u); }   // Pre-Processing to  // calculate values of  // lca[][], MinWeight[][] // and MaxWeight[][] static void dfs(int node,                  int parent, int h) {   // Using recursion formula to   // calculate the values   // of lca[][]   lca[node] = parent;     // Storing the level of   // each node   level[node] = h;       if (parent != -1)    {     minWeight[node] = Math.min(weight[node],                                    weight[parent]);     maxWeight[node] = Math.max(weight[node],                                    weight[parent]);   }     for (int i = 1; i < log; i++)    {     if (lca[node][i - 1] != -1)      {       // Using recursion formula to       // calculate the values of lca[][],       // MinWeight[][] and MaxWeight[][]       lca[node][i] =            lca[lca[node][i - 1]][i - 1];               minWeight[node][i] =                  Math.min(minWeight[node][i - 1],                           minWeight[lca[node][i - 1]][i - 1]);       maxWeight[node][i] =                  Math.max(maxWeight[node][i - 1],                          maxWeight[lca[node][i - 1]][i - 1]);     }   }     for (int i : graph[node])    {     if (i == parent)       continue;     dfs(i, node, h + 1);   } }   // Function to find the minimum and // maximum weights in the given range static void findMinMaxWeight(int u,                               int v) {   int minWei = Integer.MAX_VALUE;   int maxWei = Integer.MIN_VALUE;     // The node which is present   // farthest from the root node   // is taken as v If u is   // farther from root node   // then swap the two   if (level[u] > level[v])     swap(u, v);     // Finding the ancestor of v   // which is at same level as u   for (int i = log - 1; i >= 0; i--)    {     if (lca[v][i] != -1 &&          level[lca[v][i]] >= level[u])      {       // Calculating Minimum and       // Maximum Weight of node       // v till its 2^i-th ancestor       minWei = Math.min(minWei,                          minWeight[v][i]);       maxWei = Math.max(maxWei,                          maxWeight[v][i]);       v = lca[v][i];     }   }     // If u is the ancestor of v   // then u is the LCA of u and v   if (v == u)    {     System.out.print(minWei + " " +                        maxWei + "\n");   }   else   {     // Finding the node closest to the     // root which is not the common     // ancestor of u and v i.e. a node     // x such that x is not the common     // ancestor of u and v but lca[x] is     for (int i = log - 1; i >= 0; i--)      {       if(v == -1)         v++;       if (lca[v][i] != lca[u][i])        {         // Calculating the minimum of         // MinWeight of v to its 2^i-th         // ancestor and MinWeight of u         // to its 2^i-th ancestor         minWei = Math.min(minWei,                            Math.min(minWeight[v][i],                                     minWeight[u][i]));           // Calculating the maximum of         // MaxWeight of v to its 2^i-th         // ancestor and MaxWeight of u         // to its 2^i-th ancestor         maxWei = Math.max(maxWei,                            Math.max(maxWeight[v][i],                                    maxWeight[u][i]));           v = lca[v][i];         u = lca[u][i];       }     }       // Calculating the Minimum of     // first ancestor of u and v     if(u == -1)       u++;     minWei = Math.min(minWei,                       Math.min(minWeight[v],                                 minWeight[u]));       // Calculating the maximum of     // first ancestor of u and v     maxWei = Math.max(maxWei,                       Math.max(maxWeight[v],                                 maxWeight[u]));       System.out.print(minWei + " " +                        maxWei + "\n");   } }   // Driver Code public static void main(String[] args) {   // Number of nodes   int n = 5;       for (int i = 0; i < graph.length; i++)     graph[i] = new Vector();       // Add edges   addEdge(1, 2);   addEdge(1, 5);   addEdge(2, 4);   addEdge(2, 3);     weight = -1;   weight = 5;   weight = -1;   weight = 3;   weight = -2;     // Initialising lca values with -1   // Initialising MinWeight values   // with Integer.MAX_VALUE   // Initialising MaxWeight values   // with Integer.MIN_VALUE   for (int i = 1; i <= n; i++)    {     for (int j = 0; j < log; j++)      {       lca[i][j] = -1;       minWeight[i][j] = Integer.MAX_VALUE;       maxWeight[i][j] = Integer.MIN_VALUE;     }   }     // Perform DFS   dfs(1, -1, 0);     // Query 1: {1, 3}   findMinMaxWeight(1, 3);     // Query 2: {2, 4}   findMinMaxWeight(2, 4);     // Query 3: {3, 5}   findMinMaxWeight(3, 5); } }   // This code is contributed by Rajput-Ji

## Python3

 # Python3 Program to find the # maximum and minimum weight  # between two nodes in the  # given tree using LCA import sys MAX = 1000    # log2(MAX) log = 10    # Array to store the level # of each node level = [0 for i in range(MAX)];   # Initialising lca values with -1 # Initialising MinWeight values # with INT_MAX # Initialising MaxWeight values # with INT_MIN lca = [[-1 for j in range(log)]             for i in range(MAX)] minWeight = [[sys.maxsize for j in range(log)]                            for i in range(MAX)] maxWeight = [[-sys.maxsize for j in range(log)]                             for i in range(MAX)]    # Vector to store tree graph = [[] for i in range(MAX)]   # Array to store weight of nodes weight = [0 for i in range(MAX)]   def addEdge(u, v):       graph[u].append(v);     graph[v].append(u);   # Pre-Processing to calculate # values of lca[][], MinWeight[][] # and MaxWeight[][] def dfs(node, parent, h):       # Using recursion formula to     # calculate the values     # of lca[][]     lca[node] = parent;        # Storing the level of     # each node     level[node] = h;           if (parent != -1):             minWeight[node] = (min(weight[node],                                    weight[parent]));         maxWeight[node] = (max(weight[node],                                    weight[parent]));               for i in range(1, log):         if (lca[node][i - 1] != -1):                # Using recursion formula to             # calculate the values of lca[][],             # MinWeight[][] and MaxWeight[][]             lca[node][i] = lca[lca[node][i - 1]][i - 1];             minWeight[node][i] = min(minWeight[node][i - 1],                                      minWeight[lca[node][i - 1]][i - 1]);             maxWeight[node][i] = max(maxWeight[node][i - 1],                                      maxWeight[lca[node][i - 1]][i - 1]);           for i in graph[node]:            if (i == parent):             continue;         dfs(i, node, h + 1);   # Function to find the minimum # and maximum weights in the  # given range def findMinMaxWeight(u, v):        minWei = sys.maxsize     maxWei = -sys.maxsize        # The node which is present     # farthest from the root node     # is taken as v If u is     # farther from root node     # then swap the two     if (level[u] > level[v]):         u, v = v, u                # Finding the ancestor of v     # which is at same level as u     for i in range(log - 1, -1, -1):               if (lca[v][i] != -1 and             level[lca[v][i]] >=             level[u]):                # Calculating Minimum and             # Maximum Weight of node             # v till its 2^i-th ancestor             minWei = min(minWei,                           minWeight[v][i]);             maxWei = max(maxWei,                           maxWeight[v][i]);             v = lca[v][i];                # If u is the ancestor of v     # then u is the LCA of u and v     if (v == u):                  print(str(minWei) + ' ' +               str(maxWei))        else:            # Finding the node closest to the         # root which is not the common         # ancestor of u and v i.e. a node         # x such that x is not the common         # ancestor of u and v but lca[x] is         for i in range(log - 1, -1, -1):                if (lca[v][i] != lca[u][i]):                     # Calculating the minimum of                 # MinWeight of v to its 2^i-th                 # ancestor and MinWeight of u                 # to its 2^i-th ancestor                 minWei = (min(minWei,                                min(minWeight[v][i],                                   minWeight[u][i])));                    # Calculating the maximum of                 # MaxWeight of v to its 2^i-th                 # ancestor and MaxWeight of u                 # to its 2^i-th ancestor                 maxWei = max(maxWei,                               max(maxWeight[v][i],                                  maxWeight[u][i]));                    v = lca[v][i];                 u = lca[u][i];                    # Calculating the Minimum of         # first ancestor of u and v         minWei = min(minWei,                      min(minWeight[v],                           minWeight[u]));            # Calculating the maximum of         # first ancestor of u and v         maxWei = max(maxWei,                      max(maxWeight[v],                          maxWeight[u]));                   print(str(minWei) + ' ' +               str(maxWei))       # Driver code if __name__ == "__main__":           # Number of nodes     n = 5;        # Add edges     addEdge(1, 2);     addEdge(1, 5);     addEdge(2, 4);     addEdge(2, 3);        weight = -1;     weight = 5;     weight = -1;     weight = 3;     weight = -2;           # Perform DFS     dfs(1, -1, 0);        # Query 1: {1, 3}     findMinMaxWeight(1, 3);        # Query 2: {2, 4}     findMinMaxWeight(2, 4);        # Query 3: {3, 5}     findMinMaxWeight(3, 5);    # This code is contributed by Rutvik_56

## C#

 // C# Program to find the  // maximum and minimum  // weight between two nodes // in the given tree using LCA using System; using System.Collections.Generic; class GFG{   static readonly int MAX = 1000;   // Math.Log(MAX) static readonly int log = 10 ;   // Array to store the  // level of each node static int []level =         new int[MAX];   static int [,]lca =         new int[MAX, log]; static int [,]minWeight =         new int[MAX, log]; static int [,]maxWeight =         new int[MAX, log];   // List to store tree static List<int> []graph =              new List<int>[MAX];     // Array to store // weight of nodes static int []weight =         new int[MAX];     private static void swap(int x,                           int y)  {   int temp = x;   x = y;   y = temp; }   static void addEdge(int u,                      int v) {   graph[u].Add(v);   graph[v].Add(u); }   // Pre-Processing to  // calculate values of  // lca[,], MinWeight[,] // and MaxWeight[,] static void dfs(int node,                  int parent, int h) {   // Using recursion formula to   // calculate the values   // of lca[,]   lca[node, 0] = parent;     // Storing the level of   // each node   level[node] = h;       if (parent != -1)    {     minWeight[node, 0] = Math.Min(weight[node],                                    weight[parent]);     maxWeight[node, 0] = Math.Max(weight[node],                                    weight[parent]);   }     for (int i = 1; i < log; i++)    {     if (lca[node, i - 1] != -1)      {       // Using recursion formula to       // calculate the values of lca[,],       // MinWeight[,] and MaxWeight[,]       lca[node, i] =            lca[lca[node, i - 1],                i - 1];               minWeight[node, i] =                  Math.Min(minWeight[node, i - 1],                           minWeight[lca[node, i - 1],                                     i - 1]);       maxWeight[node, i] =                  Math.Max(maxWeight[node, i - 1],                          maxWeight[lca[node, i - 1],                                     i - 1]);     }   }     foreach (int i in graph[node])    {     if (i == parent)       continue;     dfs(i, node, h + 1);   } }   // Function to find the minimum and // maximum weights in the given range static void findMinMaxWeight(int u,                               int v) {   int minWei = int.MaxValue;   int maxWei = int.MinValue;     // The node which is present   // farthest from the root node   // is taken as v If u is   // farther from root node   // then swap the two   if (level[u] > level[v])     swap(u, v);     // Finding the ancestor of v   // which is at same level as u   for (int i = log - 1; i >= 0; i--)    {     if (lca[v, i] != -1 &&          level[lca[v, i]] >= level[u])      {       // Calculating Minimum and       // Maximum Weight of node       // v till its 2^i-th ancestor       minWei = Math.Min(minWei,                          minWeight[v, i]);       maxWei = Math.Max(maxWei,                          maxWeight[v, i]);       v = lca[v, i];     }   }     // If u is the ancestor of v   // then u is the LCA of u and v   if (v == u)    {     Console.Write(minWei + " " +                     maxWei + "\n");   }   else   {     // Finding the node closest to the     // root which is not the common     // ancestor of u and v i.e. a node     // x such that x is not the common     // ancestor of u and v but lca[x,0] is     for (int i = log - 1; i >= 0; i--)      {       if(v == -1)         v++;       if (lca[v, i] != lca[u, i])        {         // Calculating the minimum of         // MinWeight of v to its 2^i-th         // ancestor and MinWeight of u         // to its 2^i-th ancestor         minWei = Math.Min(minWei,                   Math.Min(minWeight[v, i],                            minWeight[u, i]));           // Calculating the maximum of         // MaxWeight of v to its 2^i-th         // ancestor and MaxWeight of u         // to its 2^i-th ancestor         maxWei = Math.Max(maxWei,                   Math.Max(maxWeight[v, i],                           maxWeight[u, i]));                   v = lca[v, i];         u = lca[u, i];       }     }       // Calculating the Minimum of     // first ancestor of u and v     if(u == -1)       u++;     minWei = Math.Min(minWei,              Math.Min(minWeight[v, 0],                        minWeight[u, 0]));       // Calculating the maximum of     // first ancestor of u and v     maxWei = Math.Max(maxWei,              Math.Max(maxWeight[v, 0],                        maxWeight[u, 0]));       Console.Write(minWei + " " +                     maxWei + "\n");   } }   // Driver Code public static void Main(String[] args) {   // Number of nodes   int n = 5;       for (int i = 0; i < graph.Length; i++)     graph[i] = new List<int>();       // Add edges   addEdge(1, 2);   addEdge(1, 5);   addEdge(2, 4);   addEdge(2, 3);     weight = -1;   weight = 5;   weight = -1;   weight = 3;   weight = -2;     // Initialising lca values with -1   // Initialising MinWeight values   // with int.MaxValue   // Initialising MaxWeight values   // with int.MinValue   for (int i = 1; i <= n; i++)    {     for (int j = 0; j < log; j++)      {       lca[i, j] = -1;       minWeight[i, j] = int.MaxValue;       maxWeight[i, j] = int.MinValue;     }   }     // Perform DFS   dfs(1, -1, 0);     // Query 1: {1, 3}   findMinMaxWeight(1, 3);     // Query 2: {2, 4}   findMinMaxWeight(2, 4);     // Query 3: {3, 5}   findMinMaxWeight(3, 5); } }   // This code is contributed by Rajput-Ji

## Javascript

 

Output

-1 5
3 5
-2 5

Time Complexity: The time taken in pre-processing is O(N logN) and every query takes O(logN) time. So the overall time complexity of the solution is O(N logN).
Auxiliary Space: O(MAX*log), for storing lca, where MAX=1000 and log=10.

My Personal Notes arrow_drop_up
Related Articles