第四周训练 | 并查集
Posted chrysanthemum
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第四周训练 | 并查集相关的知识,希望对你有一定的参考价值。
A - How Many Tables
#include<iostream> using namespace std; const int maxn = 1050; int set[maxn]; void init_set() { for(int i=0;i<=maxn;++i)set[i]=i; } int find_set(int x) { return x==set[x]?x:find_set(set[x]); } void union_set(int x,int y) { x=find_set(x); y=find_set(y); if(x!=y)set[x]=set[y]; } int main() { int t,n,m,x,y; cin>>t; while(t--) { cin>>n>>m; init_set(); for(int i=1;i<=m;++i) { cin>>x>>y; union_set(x,y); } int ans=0; for(int i=1;i<=n;++i) { if(set[i]==i)ans++; } cout<<ans<<endl; } return 0; }
优化版,降低了树高:
#include<iostream> using namespace std; const int maxn = 1050; int set[maxn],height[maxn]; void init_set() { for(int i=0;i<=maxn;++i) { set[i]=i; height[i]=0; } } int find_set(int x) { return x==set[x]?x:find_set(set[x]); } void union_set(int x,int y) { x=find_set(x); y=find_set(y); if(height[x]==height[y]) { height[x]+=1; set[y]=x; } else { if(height[x]<height[y])set[x]=y; else set[y]=x; } } int main() { int t,n,m,x,y; cin>>t; while(t--) { cin>>n>>m; init_set(); for(int i=1;i<=m;++i) { cin>>x>>y; union_set(x,y); } int ans=0; for(int i=1;i<=n;++i) { if(set[i]==i)ans++; } cout<<ans<<endl; } return 0; }
路径压缩版本:
#include<iostream> using namespace std; const int maxn = 1050; int set[maxn],height[maxn]; void init_set() { for(int i=0;i<=maxn;++i) { set[i]=i; height[i]=0; } } int find_set(int x) { if(x!=set[x])set[x]=find_set(set[x]); return set[x]; } void union_set(int x,int y) { x=find_set(x); y=find_set(y); if(height[x]==height[y]) { height[x]+=1; set[y]=x; } else { if(height[x]<height[y])set[x]=y; else set[y]=x; } } int main() { int t,n,m,x,y; cin>>t; while(t--) { cin>>n>>m; init_set(); for(int i=1;i<=m;++i) { cin>>x>>y; union_set(x,y); } int ans=0; for(int i=1;i<=n;++i) { if(set[i]==i)ans++; } cout<<ans<<endl; } return 0; }
非递归写法:
#include<iostream> using namespace std; const int maxn = 1050; int set[maxn],height[maxn]; void init_set() { for(int i=0;i<=maxn;++i) { set[i]=i; height[i]=0; } } int find_set(int x) { int r=x; while(set[r]!=r)r=set[r]; int i=x,j; while(i!=r) { j=set[i];set[i]=r;i=j; } return set[x]; } void union_set(int x,int y) { x=find_set(x); y=find_set(y); if(height[x]==height[y]) { height[x]+=1; set[y]=x; } else { if(height[x]<height[y])set[x]=y; else set[y]=x; } } int main() { int t,n,m,x,y; cin>>t; while(t--) { cin>>n>>m; init_set(); for(int i=1;i<=m;++i) { cin>>x>>y; union_set(x,y); } int ans=0; for(int i=1;i<=n;++i) { if(set[i]==i)ans++; } cout<<ans<<endl; } return 0; }
以上是关于第四周训练 | 并查集的主要内容,如果未能解决你的问题,请参考以下文章
2021牛客暑期多校训练营10 F.Train Wreck(栈,并查集,优先队列,贪心)