# Maximum weighted edge in path between two nodes in an N-ary tree using binary lifting

• Difficulty Level : Expert
• Last Updated : 19 Apr, 2022

Given an N-ary tree with weighted edge and Q queries where each query contains two nodes of the tree. The task is to find the maximum weighted edge in the simple path between these two nodes.
Examples: Naive Approach: A simple solution is to traverse the whole tree for each query and find the path between the two nodes.
Efficient Approach: The idea is to use binary lifting to pre-compute the maximum weighted edge from every node to every other node at distance of some . We will store the maximum weighted edge till level. and where

• j is the node and
• i is the distance of • dp[i][j] stores the parent of j at • distance if present, else it will store 0
• mx[i][j] stores the maximum edge from node j to the parent of this node at • distance.

We’ll do a depth-first search to find all the parents at distance and their weight and then precompute parents and maximum edges at every distance.
Below is the implementation of the above approach:

## C++

 `// C++ implementation to find the``// maximum weighted edge in the simple``// path between two nodes in N-ary Tree` `#include ` `using` `namespace` `std;` `const` `int` `N = 100005;` `// Depths of Nodes``vector<``int``> level(N);``const` `int` `LG = 20;` `// Parent at every 2^i level``vector > dp(LG, vector<``int``>(N));` `// Maximum node at every 2^i level``vector > mx(LG, vector<``int``>(N));` `// Graph that stores destinations``// and its weight``vector > > v(N);``int` `n;` `// Function to traverse the nodes``// using the Depth-First Search Traversal``void` `dfs_lca(``int` `a, ``int` `par, ``int` `lev)``{``    ``dp[a] = par;``    ``level[a] = lev;``    ``for` `(``auto` `i : v[a]) {` `        ``// Condition to check if its``        ``// equal to its parent then skip``        ``if` `(i.first == par)``            ``continue``;``        ``mx[i.first] = i.second;` `        ``// DFS Recursive Call``        ``dfs_lca(i.first, a, lev + 1);``    ``}``}` `// Function to find the ancestor``void` `find_ancestor()``{` `    ``// Loop to set every 2^i distance``    ``for` `(``int` `i = 1; i < LG; i++) {``        ``// Loop to calculate for``        ``// each node in the N-ary tree``        ``for` `(``int` `j = 1; j <= n; j++) {``            ``dp[i][j]``                ``= dp[i - 1][dp[i - 1][j]];` `            ``// Storing maximum edge``            ``mx[i][j]``                ``= max(mx[i - 1][j],``                      ``mx[i - 1][dp[i - 1][j]]);``        ``}``    ``}``}` `int` `getMax(``int` `a, ``int` `b)``{``    ``// Swaping if node a is at more depth``    ``// than node b because we will``    ``// always take at more depth``    ``if` `(level[b] < level[a])``        ``swap(a, b);` `    ``int` `ans = 0;` `    ``// Difference between the depth of``    ``// the two given nodes``    ``int` `diff = level[b] - level[a];``    ``while` `(diff > 0) {``        ``int` `log` `= log2(diff);``        ``ans = max(ans, mx[``log``][b]);` `        ``// Changing Node B to its``        ``// parent at 2 ^ i distance``        ``b = dp[``log``][b];` `        ``// Subtracting distance by 2^i``        ``diff -= (1 << ``log``);``    ``}` `    ``// Take both a, b to its``    ``// lca and find maximum``    ``while` `(a != b) {``        ``int` `i = log2(level[a]);` `        ``// Loop to find the 2^ith``        ``// parent that is different``        ``// for both a and b i.e below the lca``        ``while` `(i > 0``               ``&& dp[i][a] == dp[i][b])``            ``i--;` `        ``// Updating ans``        ``ans = max(ans, mx[i][a]);``        ``ans = max(ans, mx[i][b]);` `        ``// Changing value to its parent``        ``a = dp[i][a];``        ``b = dp[i][b];``    ``}``    ``return` `ans;``}` `// Function to compute the Least``// common Ancestor``void` `compute_lca()``{``    ``dfs_lca(1, 0, 0);``    ``find_ancestor();``}` `// Driver Code``int` `main()``{``    ``// Undirected tree``    ``n = 5;``    ``v.push_back(make_pair(2, 2));``    ``v.push_back(make_pair(1, 2));``    ``v.push_back(make_pair(3, 5));``    ``v.push_back(make_pair(1, 5));``    ``v.push_back(make_pair(4, 3));``    ``v.push_back(make_pair(3, 4));``    ``v.push_back(make_pair(5, 1));``    ``v.push_back(make_pair(3, 1));` `    ``// Computing LCA``    ``compute_lca();` `    ``int` `queries[]``        ``= { { 3, 5 },``            ``{ 2, 3 },``            ``{ 2, 4 } };``    ``int` `q = 3;` `    ``for` `(``int` `i = 0; i < q; i++) {``        ``int` `max_edge = getMax(queries[i],``                              ``queries[i]);``        ``cout << max_edge << endl;``    ``}``    ``return` `0;``}`

## Java

 `// Java implementation to find the``// maximum weighted edge in the simple``// path between two nodes in N-ary Tree``import` `java.util.*;``import` `java.awt.Point;``public` `class` `Main``{``    ``static` `int` `N = ``100005``;``    ` `    ``// Depths of Nodes``    ``static` `int``[] level = ``new` `int``[N];``    ``static` `int` `LG = ``20``;``  ` `    ``// Parent at every 2^i level``    ``static` `int``[][] dp = ``new` `int``[LG][N];``  ` `    ``// Maximum node at every 2^i level``    ``static` `int``[][] mx = ``new` `int``[LG][N];``  ` `    ``// Graph that stores destinations``    ``// and its weight``    ``static` `Vector> v = ``new` `Vector>();``     ` `    ``static` `int` `n = ``0``;``  ` `    ``// Function to traverse the``    ``// nodes using the Depth-First``    ``// Search Traversal``    ``static` `void` `dfs_lca(``int` `a, ``int` `par, ``int` `lev)``    ``{``        ``dp[``0``][a] = par;``        ``level[a] = lev;``        ``for``(``int` `i = ``0``; i < v.get(a).size(); i++)``        ``{``            ``// Condition to check``            ``// if its equal to its``            ``// parent then skip``            ``if` `(v.get(a).get(i).x == par)``                ``continue``;``            ``mx[``0``][v.get(a).get(i).x] = v.get(a).get(i).y;``  ` `            ``// DFS Recursive Call``            ``dfs_lca(v.get(a).get(i).x, a, lev + ``1``);``        ``}``    ``}``  ` `    ``// Function to find the ancestor``    ``static` `void` `find_ancestor()``    ``{``        ``// Loop to set every 2^i distance``        ``for``(``int` `i = ``1``; i < ``16``; i++)``        ``{``            ``// Loop to calculate for``            ``// each node in the N-ary tree``            ``for``(``int` `j = ``1``; j < n + ``1``; j++)``            ``{``                ``dp[i][j] = dp[i - ``1``][dp[i - ``1``][j]];``  ` `                ``// Storing maximum edge``                ``mx[i][j] = Math.max(mx[i - ``1``][j], mx[i - ``1``][dp[i - ``1``][j]]);``            ``}``        ``}``    ``}``  ` `    ``static` `int` `getMax(``int` `a, ``int` `b)``    ``{``        ``// Swaping if node a is at more depth``        ``// than node b because we will``        ``// always take at more depth``        ``if` `(level[b] < level[a])``        ``{``            ``int` `temp = a;``            ``a = b;``            ``b = temp;``        ``}``  ` `        ``int` `ans = ``0``;``  ` `        ``// Difference between the``        ``// depth of the two given``        ``// nodes``        ``int` `diff = level[b] - level[a];``  ` `        ``while` `(diff > ``0``)``        ``{``            ``int` `log = (``int``)(Math.log(diff) / Math.log(``2``));``            ``ans = Math.max(ans, mx[log][b]);``  ` `            ``// Changing Node B to its``            ``// parent at 2 ^ i distance``            ``b = dp[log][b];``  ` `            ``// Subtracting distance by 2^i``            ``diff -= (``1` `<< log);``        ``}``  ` `        ``// Take both a, b to its``        ``// lca and find maximum``        ``while` `(a != b)``        ``{``            ``int` `i = (``int``)(Math.log(level[a]) / Math.log(``2``));``  ` `            ``// Loop to find the maximum 2^ith``            ``// parent the is different``            ``// for both a and b``            ``while` `(i > ``0` `&& dp[i][a] == dp[i][b])``            ``{``                ``i-=``1``;``            ``}``  ` `            ``// Updating ans``            ``ans = Math.max(ans, mx[i][a]);``            ``ans = Math.max(ans, mx[i][b]);``  ` `            ``// Changing value to``            ``// its parent``            ``a = dp[i][a];``            ``b = dp[i][b];``        ``}``  ` `        ``return` `ans;``    ``}``  ` `    ``// Function to compute the Least``    ``// common Ancestor``    ``static` `void` `compute_lca()``    ``{``        ``dfs_lca(``1``, ``0``, ``0``);``        ``find_ancestor();``    ``}``    ` `    ``public` `static` `void` `main(String[] args) {``        ``for``(``int` `i = ``0``; i < LG; i++)``        ``{``            ``for``(``int` `j = ``0``; j < N; j++)``            ``{``                ``dp[i][j] = ``0``;``                ``mx[i][j] = ``0``;``            ``}``        ``}``         ` `        ``for``(``int` `i = ``0``; i < N; i++)``        ``{``            ``v.add(``new` `Vector());``        ``}``         ` `        ``// Undirected tree``        ``v.get(``1``).add(``new` `Point(``2``, ``2``));``        ``v.get(``2``).add(``new` `Point(``1``, ``2``));``        ``v.get(``1``).add(``new` `Point(``3``, ``5``));``        ``v.get(``3``).add(``new` `Point(``1``, ``5``));``        ``v.get(``3``).add(``new` `Point(``4``, ``3``));``        ``v.get(``4``).add(``new` `Point(``3``, ``4``));``        ``v.get(``3``).add(``new` `Point(``5``, ``1``));``        ``v.get(``5``).add(``new` `Point(``3``, ``1``));``      ` `        ``// Computing LCA``        ``compute_lca();``      ` `        ``int``[][] queries``            ``= { { ``3``, ``5` `},``                ``{ ``2``, ``3` `},``                ``{ ``2``, ``4` `} };``        ``int` `q = ``3``;``      ` `        ``for` `(``int` `i = ``0``; i < q; i++) {``            ``int` `max_edge = getMax(queries[i][``0``],``                                  ``queries[i][``1``]);``            ``System.out.println(max_edge);``        ``}``    ``}``}` `// This code is contributed by decode2207.`

## Python3

 `# Python3 implementation to``# find the maximum weighted``# edge in the simple path``# between two nodes in N-ary Tree``import` `math``N ``=` `100005``;`` ` `# Depths of Nodes``level ``=` `[``0` `for` `i ``in` `range``(N)]``LG ``=` `20``;`` ` `# Parent at every 2^i level``dp ``=` `[[``0` `for` `j ``in` `range``(N)]``         ``for` `i ``in` `range``(LG)]`` ` `# Maximum node at every 2^i level``mx ``=` `[[``0` `for` `j ``in` `range``(N)]``         ``for` `i ``in` `range``(LG)]`` ` `# Graph that stores destinations``# and its weight``v ``=` `[[] ``for` `i ``in` `range``(N)]``n ``=` `0`` ` `# Function to traverse the``# nodes using the Depth-First``# Search Traversal``def` `dfs_lca(a, par, lev):` `    ``dp[``0``][a] ``=` `par;``    ``level[a] ``=` `lev;``    ` `    ``for` `i ``in` `v[a]:`` ` `        ``# Condition to check``        ``# if its equal to its``        ``# parent then skip``        ``if` `(i[``0``] ``=``=` `par):``            ``continue``;``        ``mx[``0``][i[``0``]] ``=` `i[``1``];`` ` `        ``# DFS Recursive Call``        ``dfs_lca(i[``0``], a, lev ``+` `1``);` `# Function to find the ancestor``def` `find_ancestor():`` ` `    ``# Loop to set every 2^i distance``    ``for` `i ``in` `range``(``1``, ``16``):``    ` `        ``# Loop to calculate for``        ``# each node in the N-ary tree``        ``for` `j ``in` `range``(``1``, n ``+` `1``):``        ` `            ``dp[i][j] ``=` `dp[i ``-` `1``][dp[i ``-` `1``][j]];`` ` `            ``# Storing maximum edge``            ``mx[i][j] ``=` `max``(mx[i ``-` `1``][j],``                           ``mx[i ``-` `1``][dp[i ``-` `1``][j]]);` `def` `getMax(a, b):` `    ``# Swaping if node a is at more depth``    ``# than node b because we will``    ``# always take at more depth``    ``if` `(level[b] < level[a]):``        ``a, b ``=` `b, a`` ` `    ``ans ``=` `0``;`` ` `    ``# Difference between the``    ``# depth of the two given``    ``# nodes``    ``diff ``=` `level[b] ``-` `level[a];``    ` `    ``while` `(diff > ``0``):``        ``log ``=` `int``(math.log2(diff));``        ``ans ``=` `max``(ans, mx[log][b]);`` ` `        ``# Changing Node B to its``        ``# parent at 2 ^ i distance``        ``b ``=` `dp[log][b];`` ` `        ``# Subtracting distance by 2^i``        ``diff ``-``=` `(``1` `<< log);``     ` `    ``# Take both a, b to its``    ``# lca and find maximum``    ``while` `(a !``=` `b):``        ``i ``=` `int``(math.log2(level[a]));`` ` `        ``# Loop to find the maximum 2^ith``        ``# parent the is different``        ``# for both a and b``        ``while` `(i > ``0` `and``               ``dp[i][a] ``=``=` `dp[i][b]):``            ``i``-``=``1`` ` `        ``# Updating ans``        ``ans ``=` `max``(ans, mx[i][a]);``        ``ans ``=` `max``(ans, mx[i][b]);`` ` `        ``# Changing value to``        ``# its parent``        ``a ``=` `dp[i][a];``        ``b ``=` `dp[i][b];``    ` `    ``return` `ans;`` ` `# Function to compute the Least``# common Ancestor``def` `compute_lca():``    ` `    ``dfs_lca(``1``, ``0``, ``0``);``    ``find_ancestor();` `# Driver code``if` `__name__``=``=``"__main__"``:``    ` `    ``# Undirected tree``    ``n ``=` `5``;``    ``v[``1``].append([``2``, ``2``]);``    ``v[``2``].append([``1``, ``2``]);``    ``v[``1``].append([``3``, ``5``]);``    ``v[``3``].append([``1``, ``5``]);``    ``v[``3``].append([``4``, ``3``]);``    ``v[``4``].append([``3``, ``4``]);``    ``v[``3``].append([``5``, ``1``]);``    ``v[``5``].append([``3``, ``1``]);`` ` `    ``# Computing LCA``    ``compute_lca();`` ` `    ``queries``=` `[[``3``, ``5``], [``2``, ``3``], [``2``,``4``]]``    ``q ``=` `3``;``    ` `    ``for` `i ``in` `range``(q):``        ``max_edge ``=` `getMax(queries[i][``0``],``                          ``queries[i][``1``]);``        ``print``(max_edge)``        ` `# This code is contributed by Rutvik_56`

## C#

 `// C# implementation to find the``// maximum weighted edge in the simple``// path between two nodes in N-ary Tree``using` `System;``using` `System.Collections.Generic;``class` `GFG {``    ` `    ``static` `int` `N = 100005;``   ` `    ``// Depths of Nodes``    ``static` `int``[] level = ``new` `int``[N];``    ``static` `int` `LG = 20;`` ` `    ``// Parent at every 2^i level``    ``static` `int``[,] dp = ``new` `int``[LG, N];`` ` `    ``// Maximum node at every 2^i level``    ``static` `int``[,] mx = ``new` `int``[LG, N];`` ` `    ``// Graph that stores destinations``    ``// and its weight``    ``static` `List>> v = ``new` `List>>();``    ` `    ``static` `int` `n = 0;`` ` `    ``// Function to traverse the``    ``// nodes using the Depth-First``    ``// Search Traversal``    ``static` `void` `dfs_lca(``int` `a, ``int` `par, ``int` `lev)``    ``{``        ``dp[0,a] = par;``        ``level[a] = lev;``        ``for``(``int` `i = 0; i < v[a].Count; i++)``        ``{``            ``// Condition to check``            ``// if its equal to its``            ``// parent then skip``            ``if` `(v[a][i].Item1 == par)``                ``continue``;``            ``mx[0,v[a][i].Item1] = v[a][i].Item2;`` ` `            ``// DFS Recursive Call``            ``dfs_lca(v[a][i].Item1, a, lev + 1);``        ``}``    ``}`` ` `    ``// Function to find the ancestor``    ``static` `void` `find_ancestor()``    ``{``        ``// Loop to set every 2^i distance``        ``for``(``int` `i = 1; i < 16; i++)``        ``{``            ``// Loop to calculate for``            ``// each node in the N-ary tree``            ``for``(``int` `j = 1; j < n + 1; j++)``            ``{``                ``dp[i,j] = dp[i - 1,dp[i - 1,j]];`` ` `                ``// Storing maximum edge``                ``mx[i,j] = Math.Max(mx[i - 1,j], mx[i - 1,dp[i - 1,j]]);``            ``}``        ``}``    ``}`` ` `    ``static` `int` `getMax(``int` `a, ``int` `b)``    ``{``        ``// Swaping if node a is at more depth``        ``// than node b because we will``        ``// always take at more depth``        ``if` `(level[b] < level[a])``        ``{``            ``int` `temp = a;``            ``a = b;``            ``b = temp;``        ``}`` ` `        ``int` `ans = 0;`` ` `        ``// Difference between the``        ``// depth of the two given``        ``// nodes``        ``int` `diff = level[b] - level[a];`` ` `        ``while` `(diff > 0)``        ``{``            ``int` `log = (``int``)(Math.Log(diff) / Math.Log(2));``            ``ans = Math.Max(ans, mx[log,b]);`` ` `            ``// Changing Node B to its``            ``// parent at 2 ^ i distance``            ``b = dp[log,b];`` ` `            ``// Subtracting distance by 2^i``            ``diff -= (1 << log);``        ``}`` ` `        ``// Take both a, b to its``        ``// lca and find maximum``        ``while` `(a != b)``        ``{``            ``int` `i = (``int``)(Math.Log(level[a]) / Math.Log(2));`` ` `            ``// Loop to find the maximum 2^ith``            ``// parent the is different``            ``// for both a and b``            ``while` `(i > 0 && dp[i,a] == dp[i,b])``            ``{``                ``i-=1;``            ``}`` ` `            ``// Updating ans``            ``ans = Math.Max(ans, mx[i,a]);``            ``ans = Math.Max(ans, mx[i,b]);`` ` `            ``// Changing value to``            ``// its parent``            ``a = dp[i,a];``            ``b = dp[i,b];``        ``}`` ` `        ``return` `ans;``    ``}`` ` `    ``// Function to compute the Least``    ``// common Ancestor``    ``static` `void` `compute_lca()``    ``{``        ``dfs_lca(1, 0, 0);``        ``find_ancestor();``    ``}` `  ``static` `void` `Main() {``      ` `    ``for``(``int` `i = 0; i < LG; i++)``    ``{``        ``for``(``int` `j = 0; j < N; j++)``        ``{``            ``dp[i,j] = 0;``            ``mx[i,j] = 0;``        ``}``    ``}``    ` `    ``for``(``int` `i = 0; i < N; i++)``    ``{``        ``v.Add(``new` `List>());``    ``}``    ` `    ``// Undirected tree``    ``v.Add(``new` `Tuple<``int``,``int``>(2, 2));``    ``v.Add(``new` `Tuple<``int``,``int``>(1, 2));``    ``v.Add(``new` `Tuple<``int``,``int``>(3, 5));``    ``v.Add(``new` `Tuple<``int``,``int``>(1, 5));``    ``v.Add(``new` `Tuple<``int``,``int``>(4, 3));``    ``v.Add(``new` `Tuple<``int``,``int``>(3, 4));``    ``v.Add(``new` `Tuple<``int``,``int``>(5, 1));``    ``v.Add(``new` `Tuple<``int``,``int``>(3, 1));`` ` `    ``// Computing LCA``    ``compute_lca();`` ` `    ``int``[,] queries``        ``= { { 3, 5 },``            ``{ 2, 3 },``            ``{ 2, 4 } };``    ``int` `q = 3;`` ` `    ``for` `(``int` `i = 0; i < q; i++) {``        ``int` `max_edge = getMax(queries[i,0],``                              ``queries[i,1]);``        ``Console.WriteLine(max_edge);``    ``}``  ``}``}` `// This code is contributed by divyesh072019.`

## Javascript

 ``

Output:

```1
5
5```

Time Complexity: O(N*logN).
Auxiliary Space: O(N*logN).

My Personal Notes arrow_drop_up