
定义

步骤

路径压缩算法

int Find1(int x) //查找函数1 //递归压缩路径——可能会爆栈
{
if(pre[x] != x) pre[x] = Find1(pre[x]);
return pre[x];
}
int Find2(int x) //查找函数2 //循环压缩路径
{
int p,tmp;
p = x;
while(x != pre[x])
x = pre[x];
while(p != x)
{
tmp = pre[p];
pre[p] = x;
p = tmp;
}
return x;
void join(int x,int y) //加入函数
{
int p = Find(x);
int q = Find(y);
if(p != q) pre[p] = q;
}
}
例题

代码
/*
* @Descripttion: 并查集操作
* 输入多组数据
每组数据第一行是两个整数n(1<=n<=10^6),m(1<=m<=10^6)。分别表示元素数、操作数(初始时每个元素以自己为一个集合,元素编号是1-n)
接下来m行,每行有如下几种输入:
union x y ——表示将x所在的集合和y所在的集合合并为一个集合。
same x y ——询问x和y是否为同一个集合、为同一个集合输出1,不同集合输出0
num x ——询问x所在的集合共有多少个元素
max x ——询问x所在的集合中元素编号最大是多少
setnum ——询问现在总共有多少个集合
对于每个same、num、max、setnum操作输出一行,用一个整数表示答案。
输出:
5 10
setnum
same 1 2
union 1 2
same 1 2
union 2 3
same 1 3
union 4 5
setnum
max 1
num 4
* @version:
* @Author: sueRimn
* @Date: 2020-04-09 07:45:46
* @LastEditors: ironman
* @LastEditTime: 2020-04-09 07:50:00
*/
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
int pre[maxn],maxx[maxn],num[maxn];
int n,m,Set = 0;
int Find(int x)
{
int p,tmp;
p = x;
while(x != pre[x])
x = pre[x];
while(p!= x)
{
tmp= pre[p];
pre[p] = x;
p = tmp;
}
return x;
}
void join (int x,int y)
{
int p,q;
p = Find(x);
q = Find(y);
if(p!=q)
{
pre[p] = q;
maxx[q] = max(maxx[q],maxx[p]);
num[q] += num[p];
}
}
int main()
{
char str[10];
while(~scanf("%d%d",&n,&m)){
for(int i = 1;i<= n;i++)
{
pre[i] = i;
num[i] = 1;
maxx[i] = i;
}
Set = n;
while(m--)
{
getchar();
int x,y;
scanf("%s",str);
if(str[0]=='u'){
scanf("%d%d",&x,&y);
if(Find(x)!=Find(y)){
join(x,y);
Set--;}
}
if(str[0]=='s'&&str[1]=='a'){
scanf("%d%d",&x,&y);
if(Find(x) == Find(y)) puts("1");
else puts("0");
}
if(str[0]=='n'){
scanf("%d",&x);
printf("%d\n",num[Find(x)]);
}
if(str[0]=='m'){
scanf("%d",&x);
printf("%d\n",maxx[Find(x)]);
}
if(str[0]=='s'&&str[1]=='e') printf("%d\n",Set);
}
}
return 0;
}