一.并查集
主要操作:
主要操作:
1.合并两个不相交集合
2.判断两个元素是否属于同一集合
时间复杂度:
O(n*α(n)),其中α(x),对于x=宇宙中原子数之和,α(x)不大于4,事实上,路经压缩后的并查集的复杂度是一个很小的常数。
模板题
#include <iostream>
#include<stdio.h>
using namespace std;
//for poj 1611
const int MAXN = 30001;
int pa[MAXN],rank[MAXN],num[MAXN];
void make_set(int x){
pa[x] = x;
rank[x] = 0;
num[x] = 1;
}
int find_set(int x){
int root = x, temp;
while(pa[root] != root) root = pa[root];
while(x != root){
temp = pa[x];
pa[x] = root;
x = temp;
}
return root;
}
void union_set(int x, int y){
x = find_set(x);
y = find_set(y);
if(x == y)return ;
if(rank[x] > rank[y]){/*让rank比较高的作为父结点*/
pa[y] = x;
num[x] += num[y];
}
else {
pa[x] = y;
if(rank[x] == rank[y])
rank[y]++;
num[y] += num[x];
}
}
int main(){
int n, m, x, y, i, t, j;
while(scanf("%d%d", &n, &m) && (m || n)){
if(m == 0){
cout << "1\n"; continue;
}
for(i = 0; i < n; i++)
make_set(i);
for(i = 0; i < m; i++){
scanf("%d", &t);
scanf("%d", &x);
for(j = 1; j < t; j++){
scanf("%d", &y);
union_set(x, y);
x = y;
}
}
/*找到0所在的树的树根*/
x = find_set(0);
cout << num[x] << endl;
}
return 0;
}