一些话
拆解流程的时候没想到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]; }
形式二:
1. int find(int x){ 2. return f[x] == x ? x : f[x] = find(f[x]); 3. }
网络上还存在一种很长的形式三仅展示,不推荐使用:
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; }