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

• Difficulty Level : Hard
• Last Updated : 22 Jun, 2021

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

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

My Personal Notes arrow_drop_up