并查集是一种树型的数据结构,用于处理一些不交集(Disjoint Sets)的合并及查询问题。有一个联合-查找算法(union-find algorithm)定义了两个用于此数据结构的操作:
Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。
Union:将两个子集合并成同一个集合。
在一个并查集中,我们采用每个集合选一个特定的元素,做为整个集合的代表。
用一棵树的结构来维护一个集合,树根就是这个集合的代表元素。
每个节点有一个父节点,数组fa[i]存i的父亲,树根的父亲为自己。
基本操作:
find(x) 查询x所在集合的代表元素(树根)
find(x)== find(y)判断两个集合是否属于同一集合
fa[find(x)] = find(y) 合并两个集合
路径压缩
一条链的长度影响查找速度;然而并查集只关心根节点(代表元素),而不关注树的形态
洛谷题目
如题,现在有一个并查集,你需要完成合并和查询操作。
第一行包含两个整数 N,MN,M ,表示共有 NN 个元素和 MM 个操作。
接下来 MM 行,每行包含三个整数 Z_i,X_i,Y_iZi,Xi,Yi 。
当 Z_i=1Zi=1 时,将 X_iXi 与 Y_iYi 所在的集合合并。
当 Z_i=2Zi=2 时,输出 X_iXi 与 Y_iYi 是否在同一集合内,是的输出 Y
;否则输出 N
。
对于每一个 Z_i=2Zi=2 的操作,都有一行输出,每行包含一个大写字母,为 Y
或者 N
。
输入 #1复制
4 7 2 1 2 1 1 2 2 1 2 1 3 4 2 1 4 1 2 3 2 1 4
输出 #1复制
N Y N Y
对于 30\%30% 的数据,N \le 10N≤10,M \le 20M≤20 。
对于 70\%70% 的数据,N \le 100N≤100,M \le 10^3M≤103 。
对于 100\%100% 的数据,1\le N \le 10^41≤N≤104,1\le M \le 2\times 10^51≤M≤2×105 。
#include
#include
using namespace std;
const int MAX_SIZE = 10001;
int fa[MAX_SIZE];
// 初始化,父节点是本身
void init(int maxSize)
{
for(int i = 0; i < maxSize; i++)
{
fa[i] = i;
}
}
// 查找代表元素,(根节点)
int find(const int x)
{
// 父节点是本身即根节点
if(fa[x] == x)
{
return x;
}
// find(fa[x]) 递归找根节点
// fa[x] = find(fa[x]) 压缩路径,当前节点的父节点等于当前节点的父节点的根节点
return fa[x] = find(fa[x]);
}
// 是否属于同一个集合
bool comp(const int x, const int y)
{
return find(x) == find(y);
}
// 合并元素 x根节点的父节点等于y的根节点
void merge(const int x, const int y)
{
fa[find(x)] = find(y);
}
int main()
{
int n,m;
cin >> n >> m;
init(MAX_SIZE);
int z,x,y;
while(m--)
{
scanf("%d%d%d",&z,&x,&y);
if(z == 1)
{
merge(x, y);
}
else if(z == 2)
{
cout << (comp(x, y) ? "Y" : "N") << endl;
}
}
return 0;
}