1. 程式人生 > 其它 >2021牛客寒假演算法基礎集訓營3 G.糖果(並查集)

2021牛客寒假演算法基礎集訓營3 G.糖果(並查集)

技術標籤:2021牛客寒假演算法基礎集訓營

G.糖果

題目連結:https://ac.nowcoder.com/acm/contest/9983/G

題目描述:

在一個幼兒園裡面有n個小朋友,分別編號1,2,…,n。在這些小朋友中有一些小朋友互為朋友關係,總共有m對朋友。
作為幼兒園老師,你想買一些糖果分給小朋友,你知道第i個小朋友想要至少ai個糖果,否則他就會不開心。同時,如果一個小朋友得到的糖果數小於他某個朋友得到的糖果數,他也會不開心。
請問你最少買多少糖果才能保證每個小朋友都不會不開心呢?

輸入描述:

第一行以空格分隔的兩個整數n,m。
第二行以空格分隔的n個正整數ai。
接下來m行每行以空格分隔的兩個正整數u,v,代表u是v的朋友,v是u的朋友。

1≤n≤10^6
0≤m≤10^6
1≤ai≤10^9
1≤u,v≤n,u≠v

輸出描述:

購買的最少糖果數以保證每個小朋友都不會不開心。

示例1:

輸入
3 1
1 2 3
1 2
輸出
7
說明
給第三個小朋友買3個糖果,前兩個小朋友都買2兩個糖果,總共至少買7個糖果。注意如果給第一個小朋友只買了1個糖果,那麼他在看到自己的好朋友2有2個糖果的情況下,他就會不開心。

解題思路:

互為好朋友的人拿到的糖果數量一致,且為該小朋友所有好朋友糖果裡面的最大值(並查集的最大值)。要注意的是m對小朋友,小朋友的小朋友不一定是好朋友。

程式碼如下:

#include<iostream>
#include
<algorithm>
#include<cstdio> using namespace std; typedef long long ll; ll f[1000010],a[1000010]; int find(int x){ if(x==f[x])return x; return f[x]=find(f[x]); } int main(){ ll n,m,x,y,ans=0; cin>>n>>m; for(int i=1;i<=n;i++){ cin>>a[i]; f[i]=i; } for(int i=1;i<=m;
i++){ cin>>x>>y; ll t1=find(x),t2=find(y); f[t1]=t2; //合併互為朋友關係 a[t2]=max(a[t1],a[t2]); //更新最大值 } for(int i=1;i<=n;i++) ans+=a[find(i)]; cout<<ans<<endl; return 0; }