并查集
应用:连通子图,最小生成树,kruskal算法,最近公共祖先(LCA)
基本操作:
1.初始化init,所有元素自己是自己的父节点
2.查询find 递归查询 最终的祖先
3.合并unionn 合并最终的父节点
题目:
给出一个无向图G,求其连通分量的数量。
输入格式:
第1行输入正整数N(0<N≤1000)和E(0<E≤5000),为顶点个数和边数。 N个结点的序号依次为1~N,接下来E行每行输入连接边的两个顶点编号。
输出格式:
输出以上图的连通分量的数目。
输入样例1:
7 5 5 6 1 2 1 4 2 3 3 4
输出样例1:
3
//寻找每个数字的父节点给有没有改变如果改变了则说明连通了
//没改变(保持和自己相连接)就是不连通
//寻找每个数字的父节点给有没有改变如果改变了则说明连通了
//没改变(保持和自己相连接)就是不连通
#include<iostream>
#define MAXN 1000
using namespace std;
int fa[MAXN];
void init(int n){
for(int i = 0; i <= n;i++)
fa[i] = i;//存储每个元素的父节点
//将自己设为父节点
}
int find(int i ){
if(fa[i] == i)
return i;//自己是自己的父节点
else
{
fa[i] = find(fa[i]); //使用路径压缩
return fa[i];//返回父节点
}
}
void unionn(int i, int j){
int i_fa = find(i);//找i的父节点
int j_fa = find(j);//找j的父节点
fa[i_fa] = j_fa;//i 的祖先指向j的祖先
}
int main(){
int n,m;
int x,y;
cin>>n>>m;
init(n);
for(int i = 0;i<m;i++){
cin>>x>>y;
//fa[find(x)] = find(y);
unionn(x,y);//两个节点连接到一个父节点上,说明有数和它相连
}
int res = 0;
for(int i = 1;i <= n;i++){
if(fa[i] == i) res ++;
}
cout<<res<<endl;
}