并查集:
N 个不同的元素分布在若干个互不相交集合
中,需要进行以下3个操作:
1. 合并两个集合
2. 查询一个元素在哪个集合
3. 查询两个元素是否属于同一集合
一般用下面两个模板:
int get_par(int a) { if(par[a]!=a) par[a] = get_par(par[a]); return par[a]; } /* 也可以表示成这种形式,两种形式与数组的初始化有关。 int get_par(int a) { if(par[a]==-1) return a; return par[a] = get_par(par[a]); } */ int query(int a, int b) { return get_par(a)==get_par(b); } void merge(int a, int b) { par[get_par(a)]=get_par(b); }
《1》简单模板题。
http://poj.org/problem?id=1611
#include<iostream> using namespace std; const int MAXN = 30000; int n, m, k; int parent[MAXN+10]; int total[MAXN+10]; int GetParent(int a) { if(parent[a]!=a) parent[a]=GetParent(parent[a]); return parent[a]; } void Merge(int a, int b) { int p1 = GetParent(a); int p2 = GetParent(b); if(p1==p2) return; total[p1]+=total[p2]; parent[p2] = p1; } int main() { while(true) { scanf("%d%d", &n, &m); if(n==0&&m==0) break; for(int i=0; i<n; i++) parent[i] = i, total[i]=1; for(int i=0; i<m; ++i) { int h,s; scanf("%d", &k); scanf("%d", &h); for(int j=1; j<k; j++) { scanf("%d", &s); Merge(h, s); } } printf("%d\n", total[GetParent(0)]); } return 0; }