📜  根据给定条件可以在朋友之间收集的最大金额

📅  最后修改于: 2021-10-25 04:44:55             🧑  作者: Mango

给定的阵列ARR [](基于1的索引)由N的正整数,使得ARR [i]表示i的量。还给出了两个二维数组,比如friends[][2]groups[][2],这样每对friends[i][0]friends[i][1]都是朋友并形成组。每对groups[i][0]groups[i][0]表示包含groups[i][0]的朋友, groups[i][1]可以是他们之间的朋友。

任务是在以下条件的基础上找到可以在他们之间收集的最大金额:

  • 如果AB是朋友, BC是朋友,那么AC是朋友。
  • 如果一群有A的人和一群有B的人之间可以建立友谊,如果一群B和一群C之间可以建立友谊,那么一群A和一群人之间可以建立友谊的C。
  • 一组朋友形成组。

例子:

方法:给定的问题可以通过组成一个朋友小组来解决,并找出每个小组可以拥有的钱数。这个想法是通过使组成员之一成为父级来使用 Disjoint Set Union。请按照以下步骤解决问题:

  • 在形成组时,添加每组朋友的数量,并将该数量存储在该组的父级中。
  • 在不同组之间添加一条边,其中一条边的两个顶点表明这两个组可以是彼此的朋友。
  • 在组的父成员之间添加一条边。
  • 由于父节点存储相应组拥有的货币数量,因此问题简化为找到从节点到叶节点的最大总和路径,其中路径中的每个节点表示该组拥有的货币数量。
  • 完成上述步骤后,打印出可收集的最大金额值。

下面是上述方法的实现:

C++
// C++ program for the above approach
 
#include 
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 v[N];
 
// Function to find the parent of each
// node in the graph
int 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 groups
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]) {
        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 friends
void 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 friends
void maximumMoney(
    int n, int amt[],
    vector > friends,
    vector > 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 Code
signed main()
{
    int amt[] = { 5, 2, 3, 6,
                  1, 9, 8 };
    n = sizeof(amt) / sizeof(amt[0]);
 
    vector > friends
        = { { 1, 2 }, { 2, 3 }, { 4, 5 }, { 6, 7 } };
    vector > groups
        = { { 1, 4 }, { 1, 6 } };
    maximumMoney(n, amt, friends, groups);
 
    return 0;
}


Python3
# Python3 program for the above approach
N = 100001
 
amt = [0] * N
dp = [0] * N
c = [0] * N
parent = [0] * N
sz = [0] * N
v = [[] for i in range(N)]
 
# Function to find the parent of each
# node in the graph
def 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 groups
def 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 friends
def 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 friends
def 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 Code
amt = [ 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


Javascript


输出
27

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

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。