给定的阵列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]可以是他们之间的朋友。
任务是在以下条件的基础上找到可以在他们之间收集的最大金额:
- 如果A和B是朋友, B和C是朋友,那么A和C是朋友。
- 如果一群有A的人和一群有B的人之间可以建立友谊,如果一群B和一群C之间可以建立友谊,那么一群A和一群人之间可以建立友谊的C。
- 一组朋友形成组。
例子:
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
方法:给定的问题可以通过组成一个朋友小组来解决,并找出每个小组可以拥有的钱数。这个想法是通过使组成员之一成为父级来使用 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 现场工作专业课程和学生竞争性编程现场课程。