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.

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.

      MinWeight[i][j] =\begin{cases} min (weight[i], weight[parent[i]]) & \text{ ;if } j=0 \\ min( MinWeight[i][j-1], MinWeight[lca[node][i - 1]][i - 1]) & \text{ ;if } j<0 \end{cases}

      MaxWeight[i][j] =\begin{cases} max (weight[i], weight[parent[i]]) & \text{ ;if } j=0 \\ max( MaxWeight[i][j-1], MaxWeight[lca[node][i - 1]][i - 1]) & \text{ ;if } j<0 \end{cases}

  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

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ Program to find the maximum and
// minimum weight between two nodes
// in the given tree using LCA
  
#include <bits/stdc++.h>
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][0] = parent;
  
    // Storing the level of
    // each node
    level[node] = h;
    if (parent != -1) {
        minWeight[node][0]
            = min(weight[node],
                  weight[parent]);
        maxWeight[node][0]
            = 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][0] 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][0],
                      minWeight[u][0]));
  
        // Calculating the maximum of
        // first ancestor of u and v
        maxWei
            = max(maxWei,
                  max(maxWeight[v][0],
                      maxWeight[u][0]));
  
        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] = -1;
    weight[2] = 5;
    weight[3] = -1;
    weight[4] = 3;
    weight[5] = -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;
}

chevron_right


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

competitive-programming-img




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.