目录
题目链接
C - Rumor
一些话
拆解流程的时候没想到res 开long long,但写的时候想到了,一开始还庆幸自己这次这么机灵,结果debug一直de不出错误点,还是靠学长提醒才发现printf没有用%lld。。。
还有一开始用标准find然后tle,以后还是都用路径压缩find好了
自己总结的路径压缩find套路有瑕疵,一直没发现,也是靠学长指点才发现错误。。
流程
父节点数组
值数组
find注意此题卡路径压缩
标准un加一个值比较,小的做父节点
编号1-n,q次关系
fori = 1 I <= n
读入值
whileq--
读入a,b
un(a,b)
while外查询并查集数
cnt改为res ,res += v[i] 注意res要开long long
cout << res < < end; 注意res开long long 后printf参数要改成%lld
套路
1、路径压缩find
条件:并查集必用
形式一:
int find(int x){
if(f[x] != x) f[x] = find(f[x];
return f[x];
}
形式二:
int find(int x){
return f[x] == x ? x : f[x] = find(f[x]);
}
网络上还存在一种很长的形式三仅展示,不推荐使用:
int find(int x)
{
int r=x;
while(f[r]!=r)
r=f[r];
int i=x;
int j;
while(i!=r)
{
j=f[i];
f[i]=r;
i=j;
}
return r;
}
ac代码
#include <iostream>
using namespace std;
const int N = 1e5 + 10;
int f[N],v[N];
int find(int x){
if(f[x] != x) f[x] = find(f[x]);
return f[x];
}
void un(int a, int b){
int fa = find(a);
int fb = find(b);
if(fa != fb){
if(v[fa] > v[fb]) f[fa] = fb;
else f[fb] = fa;
}
}
int main(){
int n,q;
scanf("%d%d",&n,&q);
for(int i = 1;i <= n;i++){
f[i] = i;
scanf("%d",&v[i]);
}
while(q--){
int a, b;
scanf("%d%d",&a,&b);
un(a,b);
}
long long res = 0;
for(int i = 1 ;i <= n;i++){
if(f[i] == i) res += v[i];
}
printf("%lld",res);
return 0;
}