基础并查集: 用于高效的查找某两个元素是否属于同一个集合;
一.普通的查找方式:
然后每次只需要判断一下是否find(x) == find(y)如果是说明他们是同一个集合, 否则不同集合;
二.并查集的实现方式:
- 和上面的方法大致相同, 唯一不同的是find函数; 每次find之后都把该集合的该支链的所有元素的父亲改成根节点;这样下次再find的时候只需要找一次就知道该元素属于哪个集合了;实现的方式也很相同,只需要把find函数稍微改一下:
int find(int x){
return x == pa[x] ? x : pa[x] = find(pa[x]);
}
例子
题目链接:
题目大意: 中文就不解释了;
做法:把同一个集合的所有元素都放到同一个集合里, 当放完之后, 检查一下0号同学在哪个集合, 再判断一下剩下的同学是否和它在同一个集合里面;
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <sstream>
#include <stack>
#include <vector>
#define clr(x) memset(x, 0, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxm = 505;
const int maxn = 30000 + 10;
typedef long long int ll;
int n, m;
int pa[maxn];
int find(int x){
return x == pa[x] ? x : pa[x] = find(pa[x]);
}
void connect(int x, int y){
int fa = find(x);
int fb = find(y);
pa[fa] = fb;
}
int main(void) {
#ifdef LOCAL
#endif
while(scanf("%d%d", &n, &m) == 2 && (n || m)){
for(int i = 0; i < n; i++) pa[i] = i;
for(int i = 0; i < m; i++){
int len; scanf("%d", &len);
int x; scanf("%d", &x);
int tp = x;
for(int i = 1; i < len; i++){
scanf("%d", &x);
connect(x, tp);
tp = x;
}
}
int ans = 0;
int p = find(0);
for(int i = 0; i < n; i++)
if(find(i) == p)
ans++;
printf("%d\n", ans);
}
return 0;
}