最大化从节点 u 和 v 的 LCA 到这些节点之一的路径总和
给定一棵由N个节点组成的树,数组edges[][3]大小为N – 1 ,使得对于edges[]中的每个{X, Y, W} ,在节点X和节点Y之间存在一条边,其权重为W和两个节点u和v ,任务是找到从节点(u, v)的最低公共祖先 (LCA) 到节点u和节点v的路径中边权重的最大和。
例子:
Input: N = 7, edges[][] = {{1, 2, 2}, {1, 3, 3}, {3, 4, 4}, {4, 6, 5}, {3, 5, 7}, {5, 7, 6}}, u = 6, v = 5
Output: 9
Explanation:
The path sum from node 3 to node 5 is 7.
The path sum from node 3 to node 6 is 4 + 5 = 9.
Therefore, the maximum among the two paths is 9.
Input: N = 4, edges[][] = {{1, 2, 3}, {2, 3, 4}, {3, 4, 5}, u = 1, v = 4
Output: 12
方法:给定的问题可以通过使用二元提升的概念来找到 LCA来解决。请按照以下步骤解决问题:
- 从给定的边输入创建树。
- 使用本文讨论的方法找到给定节点u和v的LCA 。
- 执行深度优先搜索以找到路径和,即从LCA到节点u和节点v的路径中边的权重之和,并将其存储在变量中,分别为maxPath1和maxPath2 。
- 完成上述步骤后,打印maxPath1和maxPath2的最大值作为结果。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
#define ll long long int
using namespace std;
const ll N = 100001;
const ll M = log2(N) + 1;
// Keeps the track of 2^i ancestors
ll anc[N][M];
// Keeps the track of sum of path from
// 2^i ancestor to current node
ll val[N][M];
// Stores the depth for each node
ll depth[N];
// Function to build tree to find the
// LCA of the two nodes
void build(vector > tree[],
ll x, ll p, ll w, ll d = 0)
{
// Base Case
anc[x][0] = p;
val[x][0] = w;
depth[x] = d;
// Traverse the given edges[]
for (int i = 1; i < M; i++) {
anc[x][i] = anc[anc[x][i - 1]][i - 1];
val[x][i]
= val[anc[x][i - 1]][i - 1]
+ val[x][i - 1];
}
// Traverse the edges of node x
for (auto i : tree[x]) {
if (i.first != p) {
// Recursive Call for building
// the child node
build(tree, i.first, x,
i.second, d + 1);
}
}
}
// Function to find LCA and calculate
// the maximum distance
ll findMaxPath(ll x, ll y)
{
if (x == y)
return 1;
// Stores the path sum from LCA
// to node x and y
ll l = 0, r = 0;
// If not on same depth, then
// make the the same depth
if (depth[x] != depth[y]) {
// Find the difference
ll dif = abs(depth[x] - depth[y]);
if (depth[x] > depth[y])
swap(x, y);
for (int i = 0; i < M; i++) {
if ((1ll << i) & (dif)) {
// Lifting y to reach the
// depth of node x
r += val[y][i];
// Value of weights path
// traversed to r
y = anc[y][i];
}
}
}
// If x == y the LCA is reached,
if (x == y)
return r + 1;
// And the maximum distance
for (int i = M - 1; i >= 0; i--) {
if (anc[x][i] != anc[y][i]) {
// Lifting both node x and y
// to reach LCA
l += val[x][i];
r += val[y][i];
x = anc[x][i];
y = anc[y][i];
}
}
l += val[x][0];
r += val[y][0];
// Return the maximum path sum
return max(l, r);
}
// Driver Code
int main()
{
// Given Tree
ll N = 7;
vector > tree[N + 1];
tree[1].push_back({ 2, 2 });
tree[2].push_back({ 1, 2 });
tree[1].push_back({ 3, 3 });
tree[2].push_back({ 1, 3 });
tree[3].push_back({ 4, 4 });
tree[4].push_back({ 3, 4 });
tree[4].push_back({ 6, 5 });
tree[6].push_back({ 4, 5 });
tree[3].push_back({ 5, 7 });
tree[5].push_back({ 3, 7 });
tree[5].push_back({ 7, 6 });
tree[7].push_back({ 5, 6 });
// Building ancestor and val[] array
build(tree, 1, 0, 0);
ll u, v;
u = 6, v = 5;
// Function Call
cout << findMaxPath(u, v);
return 0;
}
Java
// Java program for the above approach
import java.util.*;
class GFG {
static int N = 100001;
static int M = (int) Math.log(N) + 1;
static class pair {
int first, second;
public pair(int first, int second) {
this.first = first;
this.second = second;
}
}
// Keeps the track of 2^i ancestors
static int[][] anc = new int[N][M];
// Keeps the track of sum of path from
// 2^i ancestor to current node
static int[][] val = new int[N][M];
// Stores the depth for each node
static int[] depth = new int[N];
// Function to build tree to find the
// LCA of the two nodes
static void build(Vector tree[], int x, int p, int w, int d) {
// Base Case
anc[x][0] = p;
val[x][0] = w;
depth[x] = d;
// Traverse the given edges[]
for (int i = 1; i < M; i++) {
anc[x][i] = anc[anc[x][i - 1]][i - 1];
val[x][i] = val[anc[x][i - 1]][i - 1] + val[x][i - 1];
}
// Traverse the edges of node x
for (pair i : tree[x]) {
if (i.first != p) {
// Recursive Call for building
// the child node
build(tree, i.first, x, i.second, d + 1);
}
}
}
// Function to find LCA and calculate
// the maximum distance
static int findMaxPath(int x, int y) {
if (x == y)
return 1;
// Stores the path sum from LCA
// to node x and y
int l = 0, r = 0;
// If not on same depth, then
// make the the same depth
if (depth[x] != depth[y]) {
// Find the difference
int dif = Math.abs(depth[x] - depth[y]);
if (depth[x] > depth[y]) {
int t = x;
x = y;
y = t;
}
for (int i = 0; i < M; i++) {
if (((1L << i) & (dif)) != 0) {
// Lifting y to reach the
// depth of node x
r += val[y][i];
// Value of weights path
// traversed to r
y = anc[y][i];
}
}
}
// If x == y the LCA is reached,
if (x == y)
return r + 1;
// And the maximum distance
for (int i = M - 1; i >= 0; i--) {
if (anc[x][i] != anc[y][i]) {
// Lifting both node x and y
// to reach LCA
l += val[x][i];
r += val[y][i];
x = anc[x][i];
y = anc[y][i];
}
}
l += val[x][0];
r += val[y][0];
// Return the maximum path sum
return Math.max(l, r);
}
// Driver Code
public static void main(String[] args) {
// Given Tree
int N = 7;
@SuppressWarnings("unchecked")
Vector[] tree = new Vector[N + 1];
for (int i = 0; i < tree.length; i++)
tree[i] = new Vector();
tree[1].add(new pair(2, 2));
tree[2].add(new pair(1, 2));
tree[1].add(new pair(3, 3));
tree[2].add(new pair(1, 3));
tree[3].add(new pair(4, 4));
tree[4].add(new pair(3, 4));
tree[4].add(new pair(6, 5));
tree[6].add(new pair(4, 5));
tree[3].add(new pair(5, 7));
tree[5].add(new pair(3, 7));
tree[5].add(new pair(7, 6));
tree[7].add(new pair(5, 6));
// Building ancestor and val[] array
build(tree, 1, 0, 0, 0);
int u = 6;
int v = 5;
// Function Call
System.out.print(findMaxPath(u, v));
}
}
// This code is contributed by umadevi9616
C#
// C# program for the above approach
using System;
using System.Collections.Generic;
public class GFG {
static int N = 100001;
static int M = (int) Math.Log(N) + 1;
public class pair {
public int first, second;
public pair(int first, int second) {
this.first = first;
this.second = second;
}
}
// Keeps the track of 2^i ancestors
static int[,] anc = new int[N,M];
// Keeps the track of sum of path from
// 2^i ancestor to current node
static int[,] val = new int[N,M];
// Stores the depth for each node
static int[] depth = new int[N];
// Function to build tree to find the
// LCA of the two nodes
static void build(List []tree, int x, int p, int w, int d) {
// Base Case
anc[x,0] = p;
val[x,0] = w;
depth[x] = d;
// Traverse the given edges[]
for (int i = 1; i < M; i++) {
anc[x,i] = anc[anc[x,i - 1],i - 1];
val[x,i] = val[anc[x,i - 1],i - 1] + val[x,i - 1];
}
// Traverse the edges of node x
foreach (pair i in tree[x]) {
if (i.first != p) {
// Recursive Call for building
// the child node
build(tree, i.first, x, i.second, d + 1);
}
}
}
// Function to find LCA and calculate
// the maximum distance
static int findMaxPath(int x, int y) {
if (x == y)
return 1;
// Stores the path sum from LCA
// to node x and y
int l = 0, r = 0;
// If not on same depth, then
// make the the same depth
if (depth[x] != depth[y]) {
// Find the difference
int dif = Math.Abs(depth[x] - depth[y]);
if (depth[x] > depth[y]) {
int t = x;
x = y;
y = t;
}
for (int i = 0; i < M; i++) {
if (((1L << i) & (dif)) != 0) {
// Lifting y to reach the
// depth of node x
r += val[y,i];
// Value of weights path
// traversed to r
y = anc[y,i];
}
}
}
// If x == y the LCA is reached,
if (x == y)
return r + 1;
// And the maximum distance
for (int i = M - 1; i >= 0; i--) {
if (anc[x,i] != anc[y,i]) {
// Lifting both node x and y
// to reach LCA
l += val[x,i];
r += val[y,i];
x = anc[x,i];
y = anc[y,i];
}
}
l += val[x,0];
r += val[y,0];
// Return the maximum path sum
return Math.Max(l, r);
}
// Driver Code
public static void Main(String[] args) {
// Given Tree
int N = 7;
List[] tree = new List[N + 1];
for (int i = 0; i < tree.Length; i++)
tree[i] = new List();
tree[1].Add(new pair(2, 2));
tree[2].Add(new pair(1, 2));
tree[1].Add(new pair(3, 3));
tree[2].Add(new pair(1, 3));
tree[3].Add(new pair(4, 4));
tree[4].Add(new pair(3, 4));
tree[4].Add(new pair(6, 5));
tree[6].Add(new pair(4, 5));
tree[3].Add(new pair(5, 7));
tree[5].Add(new pair(3, 7));
tree[5].Add(new pair(7, 6));
tree[7].Add(new pair(5, 6));
// Building ancestor and val[] array
build(tree, 1, 0, 0, 0);
int u = 6;
int v = 5;
// Function Call
Console.Write(findMaxPath(u, v));
}
}
// This code is contributed by umadevi9616
Javascript
输出:
9
时间复杂度: O(N*log(N))
辅助空间: O(N*log(N))