// 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<List<Tuple<int,int>>> v = new List<List<Tuple<int,int>>>();
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)
{
// Swapping 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<Tuple<int,int>>());
}
// Undirected tree
v[1].Add(new Tuple<int,int>(2, 2));
v[2].Add(new Tuple<int,int>(1, 2));
v[1].Add(new Tuple<int,int>(3, 5));
v[3].Add(new Tuple<int,int>(1, 5));
v[3].Add(new Tuple<int,int>(4, 3));
v[4].Add(new Tuple<int,int>(3, 4));
v[3].Add(new Tuple<int,int>(5, 1));
v[5].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.