Related Articles
Query to find the maximum and minimum weight between two nodes in the given tree using LCA.
• Difficulty Level : Hard
• Last Updated : 17 Nov, 2020

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 nodeint level[MAX]; int lca[MAX][log];int minWeight[MAX][log];int maxWeight[MAX][log]; // Vector to store treevector<int> graph[MAX];// Array to store weight of nodesint 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 rangevoid 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 Codeint 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 LCAimport java.util.*;class GFG{ static final int MAX = 1000; // Math.log(MAX)static final int log = 10 ; // Array to store the// level of each nodestatic 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 treestatic Vector []graph =              new Vector[MAX];   // Array to store// weight of nodesstatic 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 rangestatic 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 Codepublic 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 LCAimport sysMAX = 1000  # log2(MAX)log = 10  # Array to store the level# of each nodelevel = [0 for i in range(MAX)]; # Initialising lca values with -1# Initialising MinWeight values# with INT_MAX# Initialising MaxWeight values# with INT_MINlca = [[-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 treegraph = [[] for i in range(MAX)] # Array to store weight of nodesweight = [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 rangedef 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 codeif __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 LCAusing 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 nodestatic 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 treestatic List<int> []graph =            new List<int>[MAX];   // Array to store// weight of nodesstatic 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 rangestatic 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 Codepublic 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
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).

Want to learn from the best curated videos and practice problems, check out the C++ Foundation Course for Basic to Advanced C++ and C++ STL Course for the language and STL.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.
My Personal Notes arrow_drop_up