链接:https://ac.nowcoder.com/acm/contest/9983/G
来源:牛客网
糖果
题目描述
在一个幼儿园里面有\mathit nn个小朋友,分别编号\text 1,2,…,n1,2,…,n。在这些小朋友中有一些小朋友互为朋友关系,总共有\mathit mm对朋友。
作为幼儿园老师,你想买一些糖果分给小朋友,你知道第\mathit ii个小朋友想要至少
个糖果,否则他就会不开心。
同时,如果一个小朋友得到的糖果数小于他某个朋友得到的糖果数,他也会不开心。
请问你最少买多少糖果才能保证每个小朋友都不会不开心呢?
输入描述:
第一行以空格分隔的两个整数\mathit n,mn,m。
第二行以空格分隔的\mathit nn个正整数a_{i}a
输出描述:
购买的最少糖果数以保证每个小朋友都不会不开心。
解题思路:
用并查集维护小朋友的朋友关系,每个集合中的小朋友糖果数应该相同,并且是最大的糖果数
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
#define ll long long
#define N 1000005
int fa[N],rankk[N],a[N];
inline void init(int n)
{
for(int i=1; i<=n; ++i){
fa[i] = i;
rankk[i] = 1;
}
}
int find(int x)
{
return x == fa[x] ? x : (fa[x] = find(fa[x]));
}
inline void merge(int i,int j)
{
int x = find(i),y = find(j);
if(x==y) return;
if(rankk[x]<=rankk[y])
fa[x] = y;
else fa[y] = x;
if(rankk[x]==rankk[y] && x!=y)
rankk[y]++;
}
int v[N];
int main(){
int n,m;
scanf("%d%d",&n,&m);
init(n);
for(int i=1; i<=n; ++i)
scanf("%d",&a[i]);
for(int i=0; i<m; ++i){
int u,v;
scanf("%d%d",&u,&v);
merge(u,v);
}
for(int i=1; i<=n; ++i){
int fa = find(i);
a[fa] = max(a[i],a[fa]);//求出每个集合的最大糖果数并赋值父节点
}
ll ans = 0;
for(int i=1; i<=n; ++i){
ans += a[find(i)]; //每个小朋友的糖果数就是父节点的糖果数
}
printf("%lld\n",ans);
return 0;
}