📌  相关文章
📜  最大化给定根树中节点对之间的差异,使得一个节点是另一个节点的祖先

📅  最后修改于: 2022-05-13 01:57:09.963000             🧑  作者: Mango

最大化给定根树中节点对之间的差异,使得一个节点是另一个节点的祖先

给定一个由N个节点组成的通用树,其值从0(N – 1) ,其中数组P[]中的第 P[i ]个节点表示第 i节点的父节点(基于 1 的索引) 。每个第 i节点都附加一个权重,在数组W[]中给出。任务是找到一对节点(u, v),使得uv的祖先,并且W u - W v被最大化。

注意:在数组P[]中, -1表示根节点。如果只有一个节点,则打印-1

例子:

方法:给定问题可以通过在N-ary Tree上使用广度优先搜索来标记给定树P[]的祖先编号,然后使用 DFS Traversal 并通过考虑每个节点找到最大差异maxDiff来解决给定问题作为一个祖先,其对应的节点具有较少的祖先值。请按照以下步骤解决问题:

  • 定义一个函数dfs(int src, int val, vector & W)并执行以下任务:
    • visited[src]的值设置为true
    • 使用变量邻居迭代范围[0, size) ,其中size是行树 [cur]的大小,并执行以下任务:
      • 如果visited[neighbor]并且祖先[neighbor]大于祖先[src]则将maxDiff的值设置为maxDiffval – W[neighbor-1]的最大值。
      • 调用函数dfs(neighbor, val, W)
  • 定义一个函数bfs(int src, int N)并执行以下任务:
    • 将向量visited[N + 1]赋值为false。
    • 初始化队列q[]
    • ansectorNum[src]的值设置为0 ,并将visited[src]的值设置为true
    • 将值src排入队列q[]
    • 在while循环中遍历直到队列q[]不为空并执行以下任务:
      • 将变量cur初始化为队列q[]的前端元素并从队列q[] 中出列。
      • 迭代范围[0, size) ,其中size是使用变量neighbor的行树 [cur]的大小,如果visited[neighbor]false ,则将其设置为true并将其排入队列q[]并设置祖先[neighbor]的值为(ancestor[cur] + 1)
  • 初始化向量tree[][]、visited[]祖先Num[]
  • 将变量maxDiff初始化为INT_MIN以存储答案。
  • 将向量tree[][]的大小调整为(N + 1)
  • 将向量visited[N + 1]赋值为false ,并将祖先Num[N+1]赋值为0
  • 初始化变量src
  • 使用变量i遍历范围[0, N) ,如果P[ I ]-1 ,则将src的值设置为i 。否则,将行i+1中的值P[ I ]和行P [ I ]中的值i + 1推入向量树[][]
  • 调用函数bfs(src, N+1)进行广度优先搜索。
  • 将向量visited[N+1]赋值为false
  • 调用函数dfs(src, W[src], W)执行深度优先搜索。
  • 使用变量i迭代范围[0, N)并执行以下步骤:
    • 如果i等于src ,则继续。否则,将向量visited[N+1]赋值为false
    • 调用函数dfs(i+1, W[i], W)
  • 执行上述步骤后,打印maxDiff的值作为答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
 
vector > tree;
vector visited;
vector ancestorNum;
 
// Stores the maximum difference
int maxDiff = INT_MIN;
 
// DFS traversal for source node as src
void dfs(int src, int val, vector& W)
{
 
    // Mark src node as visited
    visited[src] = true;
 
    // Traverse the tree
    for (auto neighbour : tree[src]) {
 
        // Check neighbour node is not
        // visited and ancestorNum should
        // be greater than the src node
        if (!visited[neighbour]
            && (ancestorNum[neighbour]
                > ancestorNum[src])) {
 
            // Update the maxDiff
            maxDiff = max(
                val - W[neighbour - 1],
                maxDiff);
 
            // Recurrence call for dfs
            dfs(neighbour, val, W);
        }
    }
}
 
// BFS traversal for source node as src
void bfs(int src, int N)
{
    // Initially mark all node as
    // not visited
    visited.assign(N, false);
 
    // Stores the nodes
    queue q;
 
    // Initially for src node mark
    // ancestorNum as 0
    ancestorNum[src] = 0;
 
    // Mark src as visited
    visited[src] = true;
 
    // Push src node into the q
    q.push(src);
 
    // Traverse the queue q
    while (!q.empty()) {
 
        // Pop front element of the q
        int cur = q.front();
        q.pop();
 
        // Traverse the tree
        for (auto neighbour : tree[cur]) {
 
            // Check neighbour node is
            // already not visited
            if (!visited[neighbour]) {
 
                // Mark the neighbour
                // node as visited
                visited[neighbour] = true;
 
                // Push the neighbour
                // node into the q
                q.push(neighbour);
 
                // Update the neighbour
                // node ancestorNum
                ancestorNum[neighbour]
                    = ancestorNum[cur] + 1;
            }
        }
    }
}
 
// Function to find the the maximized
// difference between two pair of nodes
// in rooted tree such that one node
// is ancestor of another node
void maximumDiff(vector W,
                 vector P, int N)
{
    if (N == 1) {
        cout << "-1\n";
        return;
    }
 
    // Resize the tree
    tree.resize(N + 1);
 
    // Mark all the nodes as not visited
    visited.assign(N + 1, false);
 
    // Assign all the node values
    // for ancestorNum to 0
    ancestorNum.assign(N + 1, 0);
 
    // Stores the source node to traverse
    int src;
 
    for (int i = 0; i < N; i++) {
 
        // Check P[i] is -1
        if (P[i] == -1)
 
            // Update the source node src
            src = i;
 
        else {
 
            // Store the tree values
            tree[i + 1].push_back(P[i]);
            tree[P[i]].push_back(i + 1);
        }
    }
 
    // BFS from the source node src
    bfs(src, N + 1);
 
    // Mark all the nodes as not visited
    visited.assign(N + 1, false);
 
    // DFS Call for source node src
    dfs(src, W[src], W);
 
    // For every node call dfs function
    for (int i = 0; i < N; i++) {
 
        // Check i is root node
        if (i == src)
            continue;
 
        // Mark all the nodes as
        // not visited
        visited.assign(N + 1, false);
 
        // DFS Call for source
        // node as i+1
        dfs(i + 1, W[i], W);
    }
 
    // Print the maxDiff
    cout << maxDiff << endl;
}
 
// Driver Code
int main()
{
    vector W = { 5, 10, 6, 12 };
    vector P = { 2, -1, 4, 2 };
    int N = P.size();
 
    maximumDiff(W, P, N);
 
    return 0;
}


Python3
# Python 3 program for the above approach
 
tree = []
visited = []
ancestorNum = []
 
import sys
 
# Stores the maximum difference
maxDiff = -sys.maxsize - 1
 
# DFS traversal for source node as src
def dfs(src, val, W):
    global ancestorNum
    global visited
    global tree
    global maxDiff
    # Mark src node as visited
    visited[src] = True
 
    # Traverse the tree
    for neighbour in tree[src]:
        # Check neighbour node is not
        # visited and ancestorNum should
        # be greater than the src node
        if (visited[neighbour] == False and (ancestorNum[neighbour]> ancestorNum[src])):
 
            # Update the maxDiff
            maxDiff = max(val - W[neighbour - 1],maxDiff)
 
            # Recurrence call for dfs
            dfs(neighbour, val, W)
 
# BFS traversal for source node as src
def bfs(src,N):
    global ancestorNum
    global visited
    global tree
    # Initially mark all node as
    # not visited
    visited = [False for i in range(N)]
 
    # Stores the nodes
    q = []
 
    # Initially for src node mark
    # ancestorNum as 0
    ancestorNum[src] = 0
 
    # Mark src as visited
    visited[src] = True
 
    # Push src node into the q
    q.append(src)
 
    # Traverse the queue q
    while (len(q)>0):
 
        # Pop front element of the q
        cur = q[0]
        q = q[1:]
 
        # Traverse the tree
        for neighbour in tree[cur]:
            # Check neighbour node is
            # already not visited
            if (visited[neighbour]==False):
 
                # Mark the neighbour
                # node as visited
                visited[neighbour] = True
 
                # Push the neighbour
                # node into the q
                q.append(neighbour)
 
                # Update the neighbour
                # node ancestorNum
                ancestorNum[neighbour] = ancestorNum[cur] + 1
 
# Function to find the the maximized
# difference between two pair of nodes
# in rooted tree such that one node
# is ancestor of another node
def maximumDiff(W, P, N):
    global ancestorNum
    global visited
    global tree
    if (N == 1):
        print("-1")
        return
 
    # Resize the tree
    tree = [[] for i in range(N+1)]
 
    # Mark all the nodes as not visited
    visited = [False for i in range(N + 1)]
 
    # Assign all the node values
    # for ancestorNum to 0
    ancestorNum = [0 for i in range(N + 1)]
 
    # Stores the source node to traverse
    src = 0
 
    for i in range(N):
        # Check P[i] is -1
        if (P[i] == -1):
            # Update the source node src
            src = i
 
        else:
 
            # Store the tree values
            tree[i + 1].append(P[i])
            tree[P[i]].append(i + 1)
 
    # BFS from the source node src
    bfs(src, N + 1)
 
    # Mark all the nodes as not visited
    visited = [False for i in range(N+1)]
 
    # DFS Call for source node src
    dfs(src, W[src], W)
 
    # For every node call dfs function
    for i in range(N):
        # Check i is root node
        if (i == src):
            continue
 
        # Mark all the nodes as
        # not visited
        visited = [False for i in range(N+1)]
 
        # DFS Call for source
        # node as i+1
        dfs(i + 1, W[i], W)
 
    # Print the maxDiff
    print(maxDiff)
 
# Driver Code
if __name__ == '__main__':
    W = [5, 10, 6, 12]
    P = [2, -1, 4, 2]
    N = len(P)
    maximumDiff(W, P, N)
     
    # This code is contributed by SURENDRA_GANGWAR.


输出:
6

时间复杂度: O(N 2 )
辅助空间: O(N)