并查集
并查集是一种用于判断元素是否属于同一集合的数据结构,本质是一棵树,我们一般需要维护每个结点的父亲。
并查集最起码要支持查询和合并操作。
1 int n, fa[maxn]; 2 3 inline void init() { 4 for (int i = 1; i <= n; ++i) 5 fa[i] = i; 6 } //初始化每个结点的父亲为自身 7 8 int dj_find(int i) { 9 if (i == fa[i]) return i; 10 else return fa[i] = dj_find(fa[i]); 11 } //查询最终祖先并进行路径压缩 12 13 inline void dj_merge(int a, int b) { 14 fa[dj_find(a)] = fa[dj_find(b)]; 15 } //合并就是让一个结点的最终祖先 16 //把另一个结点的最终祖先作为父亲
对于并查集的考察往往要用到加权并查集,就是在维护每个结点父亲的同时维护一些与父亲的特殊信息。
比如所在并查集的结点个数,到根结点的距离等。
1 int n, fa[maxn], size[maxn], dist[maxn]; 2 3 inline void init() { 4 for (int i = 1; i <= n; ++i) 5 fa[i] = i, dist[i] = 0, size[i] = 1; 6 } //初始化每个结点的信息 7 8 int dj_find(int i) { 9 if (i == fa[i]) return i; 10 int old = fa[i]; 11 fa[i] = dj_find(old); 12 dist[i] += dist[old]; 13 return fa[i]; 14 } //路径压缩的同时更新结点信息 15 16 inline void dj_merge(int a, int b) { 17 a = dj_find(a), b = dj_find(b); 18 fa[a] = b; 19 dist[a] = size[b]; 20 size[b] += size[a]; 21 } //此处每个结点间的距离是1