Open In App

Maximum prizes in a tree by placing M persons

Last Updated : 18 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given n nodes with exactly n-1 edges and m persons (n >=m). At each node, you can either place a person or unlimited prizes for persons. Each person would be moving towards the root i.e. node 1 and will also grab the prize if they are available on that node. The task is to maximize the sum of prizes earned by all of them.

Examples:

Input: n = 7, m = 3

1

/ | \

2 3 4

/\ |

5 6 7

Output: 6

Explanation: If we place prizes at nodes 1, 2, 3, and 4 and place persons at nodes 5, 6, and 7. Then each of them would be getting 2 prizes. So, the total sum is 6.

Input: n = 3, m = 1

1

/ \

2 3

Output: 1

Approach: This can be solved by the following approach:

For each node we have to check if we place a person here, what would be sum of prizes a person would get. This can be done if for each node we calculate exactly how much prices can be distributed and arranging them in descending order to get maximum sum with in m.

Below are the steps involved:

  • Create a adjancy list adj.
  • Traverse in adj[] array, starting from node 1.
  • For each node while traversing increase the depth by 1. Start traversing for that node.
  • Check if we place a person here, what would be sum of total prizes a person n would get here:
    • Where each node is size[node] += traversal(ans, adj, a, node, depth + 1).
  • Store them in size[node] – depth.
  • Sort them in ans array in descending order.
  • Collect total sum upto n – m.
  • Return sum.

Below is the implementation of the above apprach:

C++




// C++ Implementation of the code
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
 
vector<int> size;
 
// Function to find if we place prize here
// what would be sum of prize
int traversal(vector<long long>& ans,
            vector<vector<int> >& adj, int node,
            int parent, int depth)
{
    size[node] = 1;
    for (auto a : adj[node]) {
        if (a != parent) {
            size[node]
                += traversal(ans, adj, a, node, depth + 1);
        }
    }
    ans.push_back(size[node] - depth);
    return size[node];
}
 
// Function to find maximise sum of prizes
// grabbed by persons.
long long findMaxPrizes(int n, int m,
                        vector<vector<int> >& edges)
{
    // code here
    vector<long long> ans;
    vector<vector<int> > adj(n + 1);
    int i = 0;
    size = vector<int>(n + 1, 0);
 
    // Adding edges in adj
    while (i < edges.size()) {
        int x = edges[i][0];
        int y = edges[i][1];
 
        adj[x].push_back(y);
        adj[y].push_back(x);
        i++;
    }
 
    traversal(ans, adj, 1, -1, 1);
    sort(ans.begin(), ans.end());
    reverse(ans.begin(), ans.end());
    i = 0;
    long long sum = 0;
    while (i < n - m) {
        sum += ans[i];
        i++;
    }
 
    return sum;
}
 
// Driver code
int main()
{
    int n = 7;
    int m = 3;
    vector<vector<int> > edges
        = { { 1, 2 }, { 1, 3 }, { 1, 4 },
            { 2, 5 }, { 2, 6 }, { 4, 7 } };
 
    // Function call
    cout << findMaxPrizes(n, m, edges);
    return 0;
}


Java




import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
 
public class Main {
 
    // Global variable to store sizes of subtrees
    static List<Integer> size;
 
    // Function to perform depth-first traversal and calculate subtree sizes
    static int traversal(List<Integer> ans, HashMap<Integer, List<Integer>> adj, int node, int parent, int depth) {
        size.set(node, 1);
        for (int a : adj.get(node)) {
            if (a != parent) {
                size.set(node, size.get(node) + traversal(ans, adj, a, node, depth + 1));
            }
        }
        ans.add(size.get(node) - depth);
        return size.get(node);
    }
 
    // Function to find the maximum sum of prizes grabbed by persons
    static int findMaxPrizes(int n, int m, int[][] edges) {
        List<Integer> ans = new ArrayList<>();
 
        // Using HashMap to represent an adjacency list
        HashMap<Integer, List<Integer>> adj = new HashMap<>();
        size = new ArrayList<>(Collections.nCopies(n + 1, 0));
 
        // Populating the adjacency list
        for (int[] edge : edges) {
            int x = edge[0];
            int y = edge[1];
            adj.computeIfAbsent(x, k -> new ArrayList<>()).add(y);
            adj.computeIfAbsent(y, k -> new ArrayList<>()).add(x);
        }
 
        // Performing depth-first traversal to calculate subtree sizes
        traversal(ans, adj, 1, -1, 1);
 
        // Sorting the list of subtree sizes in descending order
        Collections.sort(ans, Collections.reverseOrder());
 
        int i = 0;
        int totalSum = 0;
 
        // Calculating the sum of prizes for the top (n - m) sizes
        while (i < n - m) {
            totalSum += ans.get(i);
            i++;
        }
 
        return totalSum;
    }
 
    // Driver code
    public static void main(String[] args) {
        int n = 7;
        int m = 3;
        int[][] edges = {{1, 2}, {1, 3}, {1, 4}, {2, 5}, {2, 6}, {4, 7}};
 
        // Function call
        System.out.println(findMaxPrizes(n, m, edges));
    }
}


Python3




from collections import defaultdict
 
# Global variable to store sizes of subtrees
size = []
 
# Function to perform depth-first traversal and calculate subtree sizes
def traversal(ans, adj, node, parent, depth):
    size[node] = 1
    for a in adj[node]:
        if a != parent:
            size[node] += traversal(ans, adj, a, node, depth + 1)
    ans.append(size[node] - depth)
    return size[node]
 
# Function to find the maximum sum of prizes grabbed by persons
def findMaxPrizes(n, m, edges):
    ans = []
     
    # Using defaultdict to represent an adjacency list
    adj = defaultdict(list)
     
    global size
    size = [0] * (n + 1)
 
    # Populating the adjacency list
    for edge in edges:
        x, y = edge
        adj[x].append(y)
        adj[y].append(x)
 
    # Performing depth-first traversal to calculate subtree sizes
    traversal(ans, adj, 1, -1, 1)
 
    # Sorting the list of subtree sizes in descending order
    ans.sort(reverse=True)
 
    i = 0
    total_sum = 0
 
    # Calculating the sum of prizes for the top (n - m) sizes
    while i < n - m:
        total_sum += ans[i]
        i += 1
 
    return total_sum
 
# Driver code
if __name__ == "__main__":
    n = 7
    m = 3
    edges = [[1, 2], [1, 3], [1, 4], [2, 5], [2, 6], [4, 7]]
 
    # Function call
    print(findMaxPrizes(n, m, edges))


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program
{
    static List<int> size;
 
    // Function to find if we place prize here
    // what would be sum of prize
    static int Traversal(List<long> ans, List<List<int>> adj,
                         int node, int parent, int depth)
    {
        size[node] = 1;
        foreach (var a in adj[node])
        {
            if (a != parent)
            {
                size[node] += Traversal(ans, adj, a, node, depth + 1);
            }
        }
        ans.Add(size[node] - depth);
        return size[node];
    }
 
    // Function to find maximise sum of prizes
    // grabbed by persons.
    static long FindMaxPrizes(int n, int m, List<List<int>> edges)
    {
        List<long> ans = new List<long>();
        List<List<int>> adj = new List<List<int>>(n + 1);
        for (int i = 0; i <= n; i++)
        {
            adj.Add(new List<int>());
        }
        int index = 0;
        size = new List<int>(new int[n + 1]);
 
        // Adding edges in adj
        foreach (var edge in edges)
        {
            int x = edge[0];
            int y = edge[1];
 
            adj[x].Add(y);
            adj[y].Add(x);
            index++;
        }
 
        Traversal(ans, adj, 1, -1, 1);
        ans.Sort();
        ans.Reverse();
        index = 0;
        long sum = 0;
        while (index < n - m)
        {
            sum += ans[index];
            index++;
        }
 
        return sum;
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int n = 7;
        int m = 3;
        List<List<int>> edges = new List<List<int>>
        {
            new List<int> { 1, 2 }, new List<int> { 1, 3 }, new List<int> { 1, 4 },
            new List<int> { 2, 5 }, new List<int> { 2, 6 }, new List<int> { 4, 7 }
        };
 
        // Function call
        Console.WriteLine(FindMaxPrizes(n, m, edges));
    }
}
 
// This code is contributed by SHIVAMGUPTA0987654321


Javascript




<script>
 
// Function to perform depth-first traversal and calculate subtree sizes
function traversal(ans, adj, node, parent, depth, size) {
    size[node] = 1;
     
    // Use get method to retrieve the adjacency list for the node
    for (let a of adj.get(node) || []) {
        if (a !== parent) {
            size[node] += traversal(ans, adj, a, node, depth + 1, size);
        }
    }
     
    ans.push(size[node] - depth);
    return size[node];
}
 
// Function to find the maximum sum of prizes grabbed by persons
function findMaxPrizes(n, m, edges) {
    let ans = [];
 
    // Using Map to represent an adjacency list
    let adj = new Map();
    let size = Array(n + 1).fill(0);
 
    // Populating the adjacency list
    for (let edge of edges) {
        let x = edge[0];
        let y = edge[1];
        adj.set(x, (adj.get(x) || []).concat(y));
        adj.set(y, (adj.get(y) || []).concat(x));
    }
 
    // Performing depth-first traversal to calculate subtree sizes
    traversal(ans, adj, 1, -1, 1, size);
 
    // Sorting the list of subtree sizes in descending order
    ans.sort((a, b) => b - a);
 
    let i = 0;
    let totalSum = 0;
 
    // Calculating the sum of prizes for the top (n - m) sizes
    while (i < n - m) {
        totalSum += ans[i];
        i++;
    }
 
    return totalSum;
}
 
// Driver code
let n = 7;
let m = 3;
let edges = [[1, 2], [1, 3], [1, 4], [2, 5], [2, 6], [4, 7]];
 
// Function call
console.log(findMaxPrizes(n, m, edges));
 
 
</script>


Output

6

Complexity Analysis:
Time Complexity: O(n log n)
Auxiliary Space: O(n)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads