📌  相关文章
📜  给定N元树的每个顶点的最大子树总和

📅  最后修改于: 2021-05-14 01:44:52             🧑  作者: Mango

给定一个由N个节点组成的N数组树,该树的根节点为1 ,边缘为{u,v}形式,并且数组values []N个整数组成。每个顶点i都有一个由values [i]表示的整数值。任务是通过将每个顶点i的值添加到其子顶点的非空子集中,找到每个顶点i可能的最大子树总和。

例子:

天真的方法:最简单的方法是从1N遍历每个顶点i的子树,并对其执行DFS遍历。对于每个顶点i ,选择其子顶点具有非负值的子集。如果所选顶点的子集为空,则搜索并打印具有最小值的节点,使其成为顶点i的子节点。否则,打印子集中存在的节点的节点值之和。

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

高效方法:想法是使用DFS遍历和动态编程方法。请按照以下步骤解决问题:

  • 初始化大小为N的数组ans [] ,以存储每个顶点的最大子树总和。
  • 对每个顶点执行DFS遍历,并为每个顶点初始化vans [v] ,并使其具有较大的负值。
  • 如果顶点v是叶顶点,则该顶点的答案将是values [v] 。因此,分配ans [v] = values [v]
  • 否则,遍历与顶点v相邻的顶点,并为每个相邻的顶点u ,将ans [v]更新为ans [v] = max(ans [u] + values [v],values [v],ans [u])
  • 完成上述步骤后,打印存储在ans []数组中的值作为每个顶点的答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
#define V 3
#define M 2
 
// Function to perform the DFS
// Traversal on the given Tree
void dfs(int v, int p,
         vector adj[],
     int ans[], int vals[])
{
     
    // To check if v is leaf vertex
    bool isLeaf = 1;
 
    // Initialize answer for vertex v
    ans[v] = INT_MIN;
 
    // Traverse adjacency list of v
    for(int u : adj[v])
    {
        if (u == p)
            continue;
             
        isLeaf = 0;
        dfs(u, v, adj, ans, vals);
 
        // Update maximum subtree sum
        ans[v] = max(ans[u] + vals[v],
                 max(ans[u], vals[u]));
    }
 
    // If v is leaf
    if (isLeaf)
    {
        ans[v] = vals[v];
    }
}
 
// Function to calculate maximum
// subtree sum for each vertex
void printAnswer(int n,
                 int edges[V][M],
                 int values[])
{
     
    // Stores the adjacency list
    vector adj[n];
     
    // Add Edegs to the list
    for(int i = 0; i < n - 1; i++)
    {
        int u = edges[i][0] - 1;
        int v = edges[i][1] - 1;
         
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
 
    // Stores largest subtree
    // sum for each vertex
    int ans[n] ;
 
    // Calculate answer
    dfs(0, -1, adj, ans, values);
 
    // Print the result
    for(auto x : ans)
    {
        cout << x << " ";
    }
}
 
// Driver Code
int main()
{
     
    // Given nodes
    int N = 4;
 
    // Give N edges
    int edges[V][M] = { { 1, 2 },
                        { 1, 3 },
                        { 3, 4 } };
 
    // Given values
    int values[] = { 1, -1, 0, 1 };
 
    // Function Call
    printAnswer(N, edges, values);
}
 
// This code is contributed by Princi Singh


Java
// Java program for the above approach
 
import java.io.*;
import java.util.ArrayList;
 
@SuppressWarnings("unchecked")
class GFG {
 
    // Function to perform the DFS
    // Traversal on the given Tree
    static void dfs(int v, int p,
                    ArrayList adj[],
                    int ans[], int vals[])
    {
 
        // To check if v is leaf vertex
        boolean isLeaf = true;
 
        // Initialize answer for vertex v
        ans[v] = Integer.MIN_VALUE;
 
        // Traverse adjacency list of v
        for (int u : adj[v]) {
            if (u == p)
                continue;
            isLeaf = false;
            dfs(u, v, adj, ans, vals);
 
            // Update maximum subtree sum
            ans[v] = Math.max(
                ans[u] + vals[v],
                Math.max(ans[u],
                         vals[u]));
        }
 
        // If v is leaf
        if (isLeaf) {
            ans[v] = vals[v];
        }
    }
 
    // Function to calculate maximum
    // subtree sum for each vertex
    static void printAnswer(
        int n, int edges[][], int values[])
    {
 
        // Stores the adjacency list
        ArrayList adj[]
            = new ArrayList[n];
 
        for (int i = 0; i < n; i++)
            adj[i] = new ArrayList<>();
 
        // Add Edegs to the list
        for (int i = 0; i < n - 1; i++) {
 
            int u = edges[i][0] - 1;
            int v = edges[i][1] - 1;
            adj[u].add(v);
            adj[v].add(u);
        }
 
        // Stores largest subtree
        // sum for each vertex
        int ans[] = new int[n];
 
        // Calculate answer
        dfs(0, -1, adj, ans, values);
 
        // Print the result
        for (int x : ans) {
            System.out.print(x + " ");
        }
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        // Given nodes
        int N = 4;
 
        // Give N edges
        int edges[][]
            = new int[][] { { 1, 2 },
                            { 1, 3 },
                            { 3, 4 } };
 
        // Given values
        int values[] = { 1, -1, 0, 1 };
 
        // Function Call
        printAnswer(N, edges, values);
    }
}


C#
// C# program for the
// above approach
using System;
using System.Collections.Generic;
class GFG{
 
// Function to perform the DFS
// Traversal on the given Tree
static void dfs(int v, int p,
                List []adj,
                int []ans, int []vals)
{
  // To check if v is leaf
  // vertex
  bool isLeaf = true;
 
  // Initialize answer for
  // vertex v
  ans[v] = int.MinValue;
 
  // Traverse adjacency list
  // of v
  foreach (int u in adj[v])
  {
    if (u == p)
      continue;
    isLeaf = false;
    dfs(u, v, adj, ans, vals);
 
    // Update maximum subtree
    // sum
    ans[v] = Math.Max(ans[u] +
                      vals[v],
             Math.Max(ans[u],
                      vals[u]));
  }
 
  // If v is leaf
  if (isLeaf)
  {
    ans[v] = vals[v];
  }
}
 
// Function to calculate maximum
// subtree sum for each vertex
static void printAnswer(int n,
                        int [,]edges,
                        int []values)
{
  // Stores the adjacency list
  List []adj =
       new List[n];
 
  for (int i = 0; i < n; i++)
    adj[i] = new List();
 
  // Add Edegs to the list
  for (int i = 0;
           i < n - 1; i++)
  {
    int u = edges[i, 0] - 1;
    int v = edges[i, 1] - 1;
    adj[u].Add(v);
    adj[v].Add(u);
  }
 
  // Stores largest subtree
  // sum for each vertex
  int []ans = new int[n];
 
  // Calculate answer
  dfs(0, -1, adj,
      ans, values);
 
  // Print the result
  foreach (int x in ans)
  {
    Console.Write(x + " ");
  }
}
 
// Driver Code
public static void Main(String[] args)
{
  // Given nodes
  int N = 4;
 
  // Give N edges
  int [,]edges = new int[,] {{1, 2},
                             {1, 3},
                             {3, 4}};
  // Given values
  int []values = {1, -1, 0, 1};
 
  // Function Call
  printAnswer(N, edges, values);
}
}
 
// This code is contributed by gauravrajput1


Python3
# Python3 program for the above approach
 
V = 3
M = 2
 
# Function to perform the DFS
# Traversal on the given Tree
def dfs(v, p):
 
    # To check if v is leaf vertex
    isLeaf = 1
 
    # Initialize answer for vertex v
    ans[v] = -10**9
 
    # Traverse adjacency list of v
    for u in adj[v]:
        if (u == p):
            continue
 
        isLeaf = 0
        dfs(u, v)
 
        # Update maximum subtree sum
        ans[v] = max(ans[u] + vals[v],max(ans[u], vals[u]))
 
    # If v is leaf
    if (isLeaf):
        ans[v] = vals[v]
 
# Function to calculate maximum
# subtree sum for each vertex
def printAnswer(n, edges, vals):
 
    # Stores the adjacency list
    # vector adj[n];
 
    # Add Edegs to the list
    for i in range(n - 1):
        u = edges[i][0] - 1
        v = edges[i][1] - 1
 
        adj[u].append(v)
        adj[v].append(u)
 
    # Calculate answer
    dfs(0, -1)
 
    # Prthe result
    for x in ans:
        print(x, end=" ")
 
# Driver Code
if __name__ == '__main__':
 
    # Given nodes
    N = 4
 
    # Give N edges
    edges=[ [ 1, 2],
            [ 1, 3],
            [ 3, 4] ]
 
    adj=[[] for i in range(N)]
    ans=[0 for i in range(N)]
 
    # Given values
    vals=[1, -1, 0, 1]
 
    # Function Call
    printAnswer(N, edges, vals)
 
# This code is contributed by mohit kumar 29


输出:
2 -1 1 1

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