概念
定义:并查集是一种树形结构,用于处理一些不相交集合的合并及查询问题
主要构成:p[]数组记录每个点的根节点,find函数是找到哪个集合或是祖宗节点,join函数用于集合的合并
代码实现
- find函数()
// 路径压缩
int find(int x)
{
if(x != p[x]) // 自己不是祖宗节点
p[x] = find(p[x]); //递归搜索
return p[x];// 最后返回
}
- join函数()
void join(int a, int b)
{
int fa = find(a);// 找出a,b的祖宗节点
int fb = find(b);
if( fa != fb) // 如果不相同,则合并
p[fa] = fb;
}
实例:
模板题:连通块中点的个数
思路:利用并查集维护size
#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int cnt[N], p[N];//cnt数组表示并查集祖宗节点中点的数量,也就是连通块的数量
// 路径压缩寻找祖宗节点
int find (int x)
{
if ( x != p[x] ) p[x] = find (p[x]);
return p[x];
}
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; ++i) p[i] = i, cnt[i] = 1;//初始化
while(m--)
{
string s;
int a, b;
cin >> s;
if( s == "C")
{
cin >> a >> b;
if(find(a) == find(b)) continue; // 相等说明在同一个集合不需要合并
cnt[find(b)] += cnt[find(a)];// 将a加入到了b,数量也也要加上
p[find(a)] = find(b); // a加到b上去
}
if( s == "Q1")
{
cin >> a >> b;
if ( find(a) == find (b)) puts("Yes");
else puts("No");
}
if ( s == "Q2")
{
cin >> a;
printf("%d\n",cnt[find(a)]);// 找出a的祖宗节点即可
}
}
return 0;
}
题二:食物链
解决办法:带权并查集
很好的博客