📌  相关文章
📜  使用二叉提升的 N 叉树中两个节点之间路径中的最大加权边

📅  最后修改于: 2021-09-07 02:13:06             🧑  作者: Mango

给定一个带有加权边和Q查询的 N 元树,其中每个查询包含树的两个节点。任务是在这两个节点之间的简单路径中找到最大加权边。
例子:

朴素的方法:一个简单的解决方案是为每个查询遍历整个树并找到两个节点之间的路径。
高效的方法:这个想法是使用二进制提升来预先计算从每个节点到某个距离的其他节点的最大加权边

2^{i}

.我们将存储最大加权边直到

2^{i}

等级。

在哪里

  • j 是节点并且
  • 我是距离

2^{i}

  • dp[i][j] 将 j 的父级存储在

2^{i}

  • 距离如果存在,否则它将存储 0
  • mx[i][j] 存储从节点 j 到这个节点的父节点的最大边在

2^{i}

  • 距离。

我们将进行深度优先搜索以找到所有的父母

2^{0}

距离和它们的权重,然后预先计算父母和最大边缘

2^{i}

距离。
下面是上述方法的实现:

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 level(N);
const int LG = 20;
 
// Parent at every 2^i level
vector > dp(LG, vector(N));
 
// Maximum node at every 2^i level
vector > mx(LG, vector(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[0][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[0][i.first] = i.second;
 
        // DFS Recursive Call
        dfs_lca(i.first, a, lev + 1);
    }
}
 
// Function to find the ansector
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;
 
    // Diffeence 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 maximum 2^ith
        // parent the is differnet
        // for both a and b
        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 Ansector
void compute_lca()
{
    dfs_lca(1, 0, 0);
    find_ancestor();
}
 
// Driver Code
int main()
{
    // Undirected tree
    n = 5;
    v[1].push_back(make_pair(2, 2));
    v[2].push_back(make_pair(1, 2));
    v[1].push_back(make_pair(3, 5));
    v[3].push_back(make_pair(1, 5));
    v[3].push_back(make_pair(4, 3));
    v[4].push_back(make_pair(3, 4));
    v[3].push_back(make_pair(5, 1));
    v[5].push_back(make_pair(3, 1));
 
    // Computing LCA
    compute_lca();
 
    int queries[][2]
        = { { 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]);
        cout << max_edge << endl;
    }
    return 0;
}


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 ansector
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;
  
    # Diffeence 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 differnet
        # 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 Ansector
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


输出:
1
5
5

时间复杂度:

O(N*logN)

如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live