并查集的算法应用
- 欧拉回路中判断图是否联通
- 最小生成树克鲁斯卡算法—Kruskal算法
并查集模板
并查集可以实现两个,查找与合并
并查集是一个树的结果,总的还说是森林
可以判断两个结点是否在一个图中,或一个图是否连通
或者实现找朋友题,朋友可以传递,判断谁和谁是否是朋友
房间是否连接
是否为亲戚
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int fa[10005];
int father(int x){
if(fa[x]==x)return x;
return fa[x]=father(fa[x]);//动态规划策略,直接
}
void unionn(int x,int y){
fa[father(y)]=father(x);
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
fa[i]=i;
}
for(int i=0;i<m;i++){
int z,x,y;
scanf("%d%d%d",&z,&x,&y);
if(z==1){
unionn(x,y);
}else if(z==2){
printf("%s\n",father(x)==father(y)?"Y":"N");
}
}
return 0;
}
例题:
HUD1232畅通工程
http://acm.hdu.edu.cn/showproblem.php?pid=1232
在最后结果中,一棵树上的结点的根结点不一定相同,但是,题目的根结点总会一棵树上
判断有几棵树的方法是,判断根是否为本身序号,因为根的根结点就是本身
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int fa[1005];
int father(int x){
if(fa[x]==x)return x;
return fa[x]=father(fa[x]);//动态规划策略,直接
}
void unionn(int x,int y){
fa[father(y)]=father(x);
}
int main(){
int n,m;
while(scanf("%d",&n)!=EOF&&n){
scanf("%d",&m);
for(int i=0;i<=n;i++)fa[i]=i;
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
unionn(a,b);
}
int sum=0;
for(int i=1;i<=n;i++){
if(fa[i]==i)sum++;
}
printf("%d\n",sum-1);
}
}
HUD How Many Tables
http://acm.hdu.edu.cn/showproblem.php?pid=1213
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
int fa[1005];
int father(int x){
if(fa[x]==x)return x;
return fa[x]=father(fa[x]);//动态规划策略,直接
}
void unionn(int x,int y){
fa[father(y)]=father(x);
}
int main(){
int t;
cin>>t;
while(t--){
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)fa[i]=i;
for(int i=0;i<m;i++){
int a,b;
scanf("%d%d",&a,&b);
unionn(a,b);
}
int sum=0;
for(int i=1;i<=n;i++){
if(fa[i]==i)sum++;
}
printf("%d\n",sum);
}
return 0;
}