Maximum money that can be collected among friends based on given conditions

Given an array arr[](1-based indexing) consisting of N positive integers such that arr[i] denotes the amount of the ith person. Also given are two 2D arrays say friends[][2] and groups[][2] such that each pair friends[i][0] and friends[i][1] are friends and form groups. Each pair groups[i][0] and groups[i][0] denotes the friends containing groups[i][0] and groups[i][1] can be friends among themselves.Â
The task is to find the maximum money that can be collected amongst themselves on the basis of the following conditions:
- If A and B are friends and B and C are friends then A and C are friends.
- If there can be a friendship between a group of people having A and a group of people having B and if there can be a friendship between a group of B and a group of C then there is a friendship between a group of A and a group of C.
- A set of friends forms the groups.
Examples:
Input: arr[] = {5, 2, 3, 6, 1, 9, 8}, friends[][] = {{1, 2}, {2, 3}, {4, 5}, {6, 7}}, groups[][] = {{1, 4}, {1, 6}}Â
Output: 27
Explanation:Total Cost in Group 1 = 5 + 2 + 3 = 10.
Total Cost in Group 2 = 6 + 1 = 7.
Total Cost in Group 3 = 9 + 8 = 17.
As the group 1 can borrow money among both the group 2 and group 3. Therefore, the maximum money collected is 10 + 17 = 27.Input: arr[] = {1, 2, 3, 4, 5, 6, 7}, friends[][] = {{1, 2}, {2, 3}, {4, 5}, {6, 7}}, groups[][] = {{1, 4}, {1, 6}}Â
Output: 19
Approach: The given problem can be solved by forming a group of friends and find the amount of money each group can have. The idea is to use Disjoint Set Union by making one of the group members a parent. Follow the below steps to solve the problem:
- While forming the group add the amount of each group of friends and store this amount with the parent of this group.
- Add an edge between different groups where two vertices of an edge show that these two groups can be friends of each other.
- Add an edge between the parent members of the group.
- Since, the parent stores the amount of money the corresponding group has, then the problem is reduced to find the maximum sum path from the node to the leaf where each node in the path represents the amount of money the group has.
- After completing the above steps, print the value of the maximum amount that can be collected.
Below is the implementation of the above approach:
C++
// C++ program for the above approachÂ
#include <bits/stdc++.h>using namespace std;#define N 100001Â
int n;int amt[N];long long dp[N], c[N];int parent[N];long long sz[N];vector<int> v[N];Â
// Function to find the parent of each// node in the graphint find(int i){    // If the parent is the same node    // itself    if (parent[i] == i)        return i;Â
    // Recursively find the parent    return parent[i] = find(parent[i]);}Â
// Function to merge the friends of// each groupsvoid Union(int a, int b){    // Find the parents of a and b    int p1 = find(a);    int p2 = find(b);Â
    // If the parents are the same    // then return    if (p1 == p2)        return;Â
    // If the size of the parent p1    // is less than the p2, then    // swap the parents p1 and p2    if (sz[p1] < sz[p2]) {        swap(p1, p2);    }Â
    parent[p2] = p1;    sz[p1] += sz[p2];Â
    // Money in the group of p2 is    // added to the p1 and p2 is    // now the member of p1    c[p1] += c[p2];Â
    // p2 is now the member of p1    c[p2] = 0;}Â
// Function to calculate the maximum// amount collected among friendsvoid dfs(int src, int par){Â Â Â Â dp[src] = c[src];Â Â Â Â long long mx = 0;Â
    // Traverse the adjacency list    // of the src node    for (auto x : v[src]) {Â
        if (x == par)            continue;Â
        dfs(x, src);Â
        // Calculate the maximum        // amount of the group        mx = max(mx, dp[x]);    }Â
    // Adding the max amount of money    // with the current group    dp[src] += mx;}Â
// Function to find the maximum money// collected among friendsvoid maximumMoney(    int n, int amt[],    vector<pair<int, int> > friends,    vector<pair<int, int> > groups){    // Iterate over the range [1, N]    for (int i = 1; i <= n; i++) {Â
        // Initialize the parent and        // the size of each node i        parent[i] = i;        sz[i] = 1;        c[i] = amt[i - 1];    }Â
    int p = friends.size();Â
    // Merging friends into groups    for (int i = 0; i < p; ++i) {Â
        // Perform the union operation        Union(friends[i].first,              friends[i].second);    }Â
    int m = groups.size();Â
    // Finding the parent of group    // in which member is present    for (int i = 0; i < m; ++i) {Â
        // Find the parent p1 and p2        int p1 = find(groups[i].first);        int p2 = find(groups[i].second);Â
        // p1 and p2 are not in same        // group then add an edge        if (p1 != p2) {Â
            // These two groups can be            // made friends. Hence,            // adding an edge            v[p1].push_back(p2);            v[p2].push_back(p1);        }    }Â
    // Starting dfs from node which    // is the parent of group in    // which 1 is present    dfs(find(1), 0);Â
    long long ans = 0;Â
    // Ans is the maximum money    // collected by each group    for (int i = 1; i <= n; i++) {        ans = max(ans, dp[find(i)]);    }Â
    // Print the answer    cout << ans << endl;}Â
// Driver Codesigned main(){    int amt[] = { 5, 2, 3, 6,                  1, 9, 8 };    n = sizeof(amt) / sizeof(amt[0]);Â
    vector<pair<int, int> > friends        = { { 1, 2 }, { 2, 3 }, { 4, 5 }, { 6, 7 } };    vector<pair<int, int> > groups        = { { 1, 4 }, { 1, 6 } };    maximumMoney(n, amt, friends, groups);Â
    return 0;} |
Java
// Java code to implement the approachimport java.io.*;import java.lang.*;import java.util.*;Â
class GFG {Â
  static int N = 100001;  static int[] amt = new int[N];  static int[] dp = new int[N];  static int[] c = new int[N];  static int[] parent = new int[N];  static int[] sz = new int[N];  static ArrayList<Integer>[] v = new ArrayList[N];Â
  // Function to find the parent of each  // node in the graph  static int find(int i)  {    // If the parent is the same node    // itself    if (parent[i] == i)      return i;    parent[i] = find(parent[i]);Â
    // Recursively find the parent    return parent[i];  }Â
  // Function to merge the friends of  // each groups  static void Union(int a, int b)  {    // Find the parents of a and b    int p1 = find(a);    int p2 = find(b);Â
    // If the parents are the same    // then return    if (p1 == p2)      return;Â
    // If the size of the parent p1    // is less than the p2, then    // swap the parents p1 and p2    if (sz[p1] < sz[p2]) {      int temp = p1;      p1 = p2;      p2 = temp;    }Â
    parent[p2] = p1;    sz[p1] += sz[p2];Â
    // Money in the group of p2 is    // added to the p1 and p2 is    // now the member of p1    c[p1] += c[p2];Â
    // p2 is now the member of p1    c[p2] = 0;  }Â
  // Function to calculate the maximum  // amount collected among friends  static void dfs(int src, int par)  {    dp[src] = c[src];    int mx = 0;Â
    // Traverse the adjacency list    // of the src node    for (int x : v[src]) {      if (x == par)        continue;      dfs(x, src);Â
      // Calculate the maximum      // amount of the group      mx = Math.max(mx, dp[x]);    }Â
    // Adding the max amount of money    // with the current group    dp[src] += mx;  }Â
  // Function to find the maximum money  // collected among friends  static void maximumMoney(int n, int[] amt,                           int[][] friends,                           int[][] groups)  {Â
    // Iterate over the range [1, N]    for (int i = 1; i <= n; i++) {Â
      // Initialize the parent and      // the size of each node i      parent[i] = i;      sz[i] = 1;      c[i] = amt[i - 1];      v[i] = new ArrayList<>();    }Â
    int p = friends.length;Â
    // Merging friends into groups    for (int i = 0; i < p; i++)Â
      // Perform the union operation      Union(friends[i][0], friends[i][1]);Â
    int m = groups.length;Â
    // Finding the parent of group    // in which member is present    for (int i = 0; i < m; i++) {Â
      // Find the parent p1 and p2      int p1 = find(groups[i][0]);      int p2 = find(groups[i][1]);Â
      // p1 and p2 are not in same      // group then add an edge      if (p1 != p2) {Â
        // These two groups can be        // made friends. Hence,        // adding an edge        v[p1].add(p2);        v[p2].add(p1);      }    }Â
    // Starting dfs from node which    // is the parent of group in    // which 1 is present    dfs(find(1), 0);Â
    int ans = 0;Â
    // Ans is the maximum money    // collected by each group    for (int i = 1; i <= n; i++)      ans = Math.max(ans, dp[find(i)]);Â
    // Print the answer    System.out.println(ans);  }  // Driver Function  public static void main(String[] args)    throws java.lang.Exception  {Â
    // Inputs    int n = 7;    int[] amt = { 5, 2, 3, 6, 1, 9, 8 };    int[][] friends      = { { 1, 2 }, { 2, 3 }, { 4, 5 }, { 6, 7 } };    int[][] groups = { { 1, 4 }, { 1, 6 } };Â
    // Function call    maximumMoney(n, amt, friends, groups);  }} |
Python3
# Python3 program for the above approachN = 100001Â
amt = [0] * Ndp = [0] * Nc = [0] * Nparent = [0] * Nsz = [0] * Nv = [[] for i in range(N)]Â
# Function to find the parent of each# node in the graphdef find(i):         # If the parent is the same node    # itself    if (parent[i] == i):        return iÂ
    parent[i] = find(parent[i])    return parent[i]Â
# Function to merge the friends of# each groupsdef Union(a, b):         # Find the parents of a and b    p1 = find(a)    p2 = find(b)Â
    # If the parents are the same    # then return    if (p1 == p2):        returnÂ
    # If the size of the parent p1    # is less than the p2, then    # swap the parents p1 and p2    if (sz[p1] < sz[p2]):        temp = p1        p1 = p2        p2 = tempÂ
    parent[p2] = p1    sz[p1] += sz[p2]Â
    # Money in the group of p2 is    # added to the p1 and p2 is    # now the member of p1    c[p1] += c[p2]Â
    # p2 is now the member of p1    c[p2] = 0Â
# Function to calculate the maximum# amount collected among friendsdef dfs(src, par):Â Â Â Â Â Â Â Â Â dp[src] = c[src]Â Â Â Â mx = 0Â
    # Traverse the adjacency list    # of the src node    for x in v[src]:        if (x == par):            continueÂ
        dfs(x, src)Â
        # Calculate the maximum        # amount of the group        mx = max(mx, dp[x])Â
    # Adding the max amount of money    # with the current group    dp[src] += mxÂ
# Function to find the maximum money# collected among friendsdef maximumMoney(n, amt, friends, groups):Â Â Â Â Â Â Â Â Â # Iterate over the range [1, N]Â Â Â Â for i in range(1, n + 1):Â
        # Initialize the parent and        # the size of each node i        parent[i] = i        sz[i] = 1        c[i] = amt[i - 1]Â
    p = len(friends)Â
    # Merging friends into groups    for i in range(p):Â
        # Perform the union operation        Union(friends[i][0], friends[i][1])Â
    m = len(groups)Â
    # Finding the parent of group    # in which member is present    for i in range(m):Â
        # Find the parent p1 and p2        p1 = find(groups[i][0])        p2 = find(groups[i][1])Â
        # p1 and p2 are not in same        # group then add an edge        if (p1 != p2):Â
            # These two groups can be            # made friends. Hence,            # adding an edge            v[p1].append(p2)            v[p2].append(p1)Â
    # Starting dfs from node which    # is the parent of group in    # which 1 is present    dfs(find(1), 0)Â
    ans = 0Â
    # Ans is the maximum money    # collected by each group    for i in range(1, n + 1):        ans = max(ans, dp[find(i)])Â
    # Print the answer    print(ans)Â
# Driver Codeamt = [ 5, 2, 3, 6, 1, 9, 8 ]n = len(amt)Â
friends = [ [ 1, 2 ], [ 2, 3 ], Â Â Â Â Â Â Â Â Â Â Â Â [ 4, 5 ], [ 6, 7 ] ]groups = [ [ 1, 4 ], [ 1, 6 ] ]Â
maximumMoney(n, amt, friends, groups)Â
# This code is contributed by _saurabh_jaiswal |
C#
// C# code to implement the approachusing System;using System.Collections.Generic;using System.Linq;Â
class GFG {Â Â static int N = 100001;Â Â static int[] amt = new int[N];Â Â static int[] dp = new int[N];Â Â static int[] c = new int[N];Â Â static int[] parent = new int[N];Â Â static int[] sz = new int[N];Â Â static List<int>[] v = new List<int>[ N ];Â
  // Function to find the parent of each  // node in the graph  static int Find(int i)  {Â
    // If the parent is the same node    // itself    if (parent[i] == i)      return i;Â
    parent[i] = Find(parent[i]);Â
    // Recursively find the parent    return parent[i];  }Â
  // Function to merge the friends of  // each groups  static void Union(int a, int b)  {Â
    // Find the parents of a and b    int p1 = Find(a);    int p2 = Find(b);Â
    // If the parents are the same    // then return    if (p1 == p2)      return;Â
    // If the size of the parent p1    // is less than the p2, then    // swap the parents p1 and p2    if (sz[p1] < sz[p2]) {      int temp = p1;      p1 = p2;      p2 = temp;    }    parent[p2] = p1;    sz[p1] += sz[p2];Â
    // Money in the group of p2 is    // added to the p1 and p2 is    // now the member of p1    c[p1] += c[p2];Â
    // p2 is now the member of p1    c[p2] = 0;  }Â
  // Function to calculate the maximum  // amount collected among friends  static void Dfs(int src, int par)  {    dp[src] = c[src];    int mx = 0;Â
    // Traverse the adjacency list    // of the src node    foreach(int x in v[src])    {      if (x == par)        continue;      Dfs(x, src);Â
      // Calculate the maximum      // amount of the group      mx = Math.Max(mx, dp[x]);    }Â
    // Adding the max amount of money    // with the current group    dp[src] += mx;  }Â
  // Function to find the maximum money  // collected among friends  static void MaximumMoney(int n, int[] amt,                           int[][] friends,                           int[][] groups)  {    // Iterate over the range [1, N]    for (int i = 1; i <= n; i++) {Â
      // Initialize the parent and      // the size of each node i      parent[i] = i;      sz[i] = 1;      c[i] = amt[i - 1];      v[i] = new List<int>();    }Â
    int p = friends.Length;Â
    // Merging friends into groups    for (int i = 0; i < p; i++)Â
      // Perform the union operation      Union(friends[i][0], friends[i][1]);Â
    int m = groups.Length;Â
    // Finding the parent of group    // in which member is present    for (int i = 0; i < m; i++) {Â
      // Find the parent p1 and p2      int p1 = Find(groups[i][0]);      int p2 = Find(groups[i][1]);Â
      // p1 and p2 are not in same      // group then add an edge      if (p1 != p2) {Â
        // These two groups can be        // made friends. Hence,        // adding an edge        v[p1].Add(p2);        v[p2].Add(p1);      }    }Â
    // Starting dfs from node which    // is the parent of group in    // which 1 is present    Dfs(Find(1), 0);Â
    int ans = 0;Â
    // Ans is the maximum money    // collected by each group    for (int i = 1; i <= n; i++)      ans = Math.Max(ans, dp[Find(i)]);Â
    // Print the answer    Console.WriteLine(ans);  }Â
  // Driver Function  static void Main(string[] args)  {Â
    // Inputs    int n = 7;    int[] amt = { 5, 2, 3, 6, 1, 9, 8 };    int[][] friends      = { new int[] { 1, 2 }, new int[] { 2, 3 },         new int[] { 4, 5 }, new int[] { 6, 7 } };    int[][] groups      = { new int[] { 1, 4 }, new int[] { 1, 6 } };Â
    // Function call    MaximumMoney(n, amt, friends, groups);  }}Â
// This code is contributed by Prajwal Kandekar |
Javascript
<script>Â
// JavaScript program for the above approachÂ
Â
let N = 100001Â
let n;let amt = new Array(N);let dp = new Array(N), c = new Array(N);let parent = new Array(N);let sz = new Array(N);let v = new Array(N).fill(0).map(() => []);Â
Â
// Function to find the parent of each// node in the graphfunction find(i) {    // If the parent is the same node    // itself    if (parent[i] == i)        return i;Â
    // Recursively find the parent    return parent[i] = find(parent[i]);}Â
// Function to merge the friends of// each groupsfunction Union(a, b) {    // Find the parents of a and b    let p1 = find(a);    let p2 = find(b);Â
    // If the parents are the same    // then return    if (p1 == p2)        return;Â
    // If the size of the parent p1    // is less than the p2, then    // swap the parents p1 and p2    if (sz[p1] < sz[p2]) {        let temp = p1;        p1 = p2;        p2 = temp;    }Â
    parent[p2] = p1;    sz[p1] += sz[p2];Â
    // Money in the group of p2 is    // added to the p1 and p2 is    // now the member of p1    c[p1] += c[p2];Â
    // p2 is now the member of p1    c[p2] = 0;}Â
// Function to calculate the maximum// amount collected among friendsfunction dfs(src, par) {Â Â Â Â dp[src] = c[src];Â Â Â Â let mx = 0;Â
    // Traverse the adjacency list    // of the src node    for (let x of v[src]) {Â
        if (x == par)            continue;Â
        dfs(x, src);Â
        // Calculate the maximum        // amount of the group        mx = Math.max(mx, dp[x]);    }Â
    // Adding the max amount of money    // with the current group    dp[src] += mx;}Â
// Function to find the maximum money// collected among friendsfunction maximumMoney(n, amt, friends, groups) {Â Â Â Â // Iterate over the range [1, N]Â Â Â Â for (let i = 1; i <= n; i++) {Â
        // Initialize the parent and        // the size of each node i        parent[i] = i;        sz[i] = 1;        c[i] = amt[i - 1];    }Â
    let p = friends.length;Â
    // Merging friends into groups    for (let i = 0; i < p; ++i) {Â
        // Perform the union operation        Union(friends[i][0],            friends[i][1]);    }Â
    let m = groups.length;Â
    // Finding the parent of group    // in which member is present    for (let i = 0; i < m; ++i) {Â
        // Find the parent p1 and p2        let p1 = find(groups[i][0]);        let p2 = find(groups[i][1]);Â
        // p1 and p2 are not in same        // group then add an edge        if (p1 != p2) {Â
            // These two groups can be            // made friends. Hence,            // adding an edge            v[p1].push(p2);            v[p2].push(p1);        }    }Â
    // Starting dfs from node which    // is the parent of group in    // which 1 is present    dfs(find(1), 0);Â
    let ans = 0;Â
    // Ans is the maximum money    // collected by each group    for (let i = 1; i <= n; i++) {        ans = Math.max(ans, dp[find(i)]);    }Â
    // Print the answer    document.write(ans + "<br>");}Â
Â
Â
// Driver CodeÂ
amt = [5, 2, 3, 6, 1, 9, 8];n = amt.length;Â
let friends    = [[1, 2], [2, 3], [4, 5], [6, 7]];let groups    = [[1, 4], [1, 6]];maximumMoney(n, amt, friends, groups);Â
</script> |
27
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!




