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

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

## Recommended: Please try your approach on {IDE} first, before moving on to the solution.

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

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

2. As we will compute the lca[][] array we will also calulate 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.  3. 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:

## CPP

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

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 Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.

1

Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.