并查集专题
并查集是可以用来处理类似家谱的需要快速合并与查找祖先的一种集合性质的数据结构
并查集模板
// size:大小 compress:路径压缩 merge_rank:按秩合并
template<int size=2500,bool compress=true,bool merge_rank=true>
class UnionFindSet{
private:
int fa[size+1];
int rank[size+1];
public:
UnionFindSet(){
for(int i=0;i<size;i++){
this->fa[i]=i;
if(merge_rank){
this->rank[i]=1;
}
}
}
int find(int x){
if(!compress){
if(this->fa[x]==x){
return x;
}
else{
return this->find(this->fa[x]);
}
}
else{
if(x==this->fa[x]){
return x;
}
else{
this->fa[x]=this->find(this->fa[x]);
return fa[x];
}
}
}
void merge(int x,int y){
if(!merge_rank){
this->fa[this->find(x)]=find(y);
}
else{
int a=this->find(x);
int b=this->find(y);
if(this->rank[a]<=this->rank[b]){
this->fa[a]=b;
}
else{
this->fa[b]=a;
}
if(rank[a]==rank[b]&&a!=b){
rank[b]++;
}
}
}
bool same(int x,int y){
return this->find(x)==this->find(y);
}
void _fa_setValue(int i,int x){
this->fa[i]=x;
}
int _fa_getValue(int i){
return this->fa[i];
}
void _rank_setValue(int i,int x){
this->rank[i]=x;
}
int _rank_getValue(int i){
return this->rank[i];
}
};
PS:以下代码均省略模板!
例题
P3367 【模板】并查集
模板题,套模板即可。
#include<bits/stdc++.h>
using namespace std;
UnionFindSet<10010,true,true> ufs;
int n,m;
int main(){
cin>>n>>m;
while(m--){
int z,x,y;
cin>>z>>x>>y;
switch(z){
case 1:
ufs.merge(x,y);
break;
default:
if(ufs.same(x,y)){
cout<<'Y'<<endl;
}
else{
cout<<'N'<<endl;
}
}
}
return 0;
}
P1551 亲戚
近似于模板题。
#include<bits/stdc++.h>
using namespace std;
UnionFindSet<10010,true,true> ufs;
int n,m,p;
int main(){
cin>>n>>m>>p;
for(int i=1;i<=m;i++){
int mi,mj;
cin>>mi>>mj;
ufs.merge(mi,mj);
}
while(p--){
int pi,pj;
cin>>pi>>pj;
if(ufs.same(pi,pj)){
cout<<"Yes"<<endl;
}
else{
cout<<"No"<<endl;
}
}
return 0;
}
P2256 一中校运会之百米跑
这道题关键在于使用std::map
容器进行字符串与int
的映射。
#include<bits/stdc++.h>
using namespace std;
UnionFindSet<20005,true,true> ufs;
map<string,int> ma;
int n,m,k;
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
string str;
cin>>str;
ma[str]=i;
}
for(int i=1;i<=m;i++){
string a,b;
cin>>a>>b;
ufs.merge(ma[a],ma[b]);
}
cin>>k;
while(k--){
string s1,s2;
cin>>s1>>s2;
if(ufs.same(ma[s1],ma[s2])){
cout<<"Yes.\n";
}
else{
cout<<"No.\n";
}
}
return 0;
}
P1682 过家家
其实这道题只要看懂题意,并且能够与图论结合,就很水了。
#include<bits/stdc++.h>
using namespace std;
UnionFindSet<100005,true,true> ufs;
int n,m,k,f;
struct Edge{
int from;int to;
} edge1[100005],edge2[100005];
bool lt[505][505];int countable[100005];
int ans=INT_MAX;
int main(){
cin>>n>>m>>k>>f;
for(int i=1;i<=m;i++){
cin>>edge1[i].from>>edge1[i].to;
}
for(int i=1;i<=f;i++){
cin>>edge2[i].from>>edge2[i].to;
}
for(int i=1;i<=f;i++){
ufs.merge(edge2[i].from,edge2[i].to);
}
for(int i=1;i<=m;i++){
if(!lt[ufs.find(edge1[i].from)][edge1[i].to]){
countable[ufs.find(edge1[i].from)]++;
lt[ufs.find(edge1[i].from)][edge1[i].to]=true;
;}
}
for(int i=1;i<=n;i++){
if(countable[i]){
ans=min(ans,countable[i]);
}
}
ans=min(ans+k,n);
printf("%d",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人