什么是“并查集”?( 二 )

这是一个递归函数,如果f[x] = x,说明这个点已经是该团伙的代表人,直接返回就好了,如果它不是该团伙的代表人,那么就返回自己指向的点的团伙代表人 。
在求getFather(3)时,f[3] != 3,返回getFather(f[3])也就是getFather(1);
在求getFather(1)时,f[1] != 1,返回getFather(f[1])也就是getFather(4);
在求getFather(4)时,f[4] == 4,返回4 。递归结束 。最后计算出3的团伙代表人是4 。
4. 查询顶点是否在同一团伙并查集的最后一种操作叫做查询,就是查询两个点是否连通(在同一团伙) 。
前面已经讲了,当两个点所在团伙“代表人”相同,则这两个点所在团伙相同 。判断两个点a、b在同一团伙的方法就是:
getFather(a) == getFather(b)
5. 完整代码const int N = 100; // 节点数量int f[N];int init() {    // 初始化    for (int i=0; i<N; i++)        f[i] == i;}int getFather(int x) {    // 查询所在团伙代表人    return f[x]==x ? x : getFather(f[x]);}int merge(int a, int b) {    // 合并操作    f[getFather(a)] = getFather(b);}bool query(int a, int b) {    // 查询操作    return getFather(a) == getFather(b);}int main() {    init();    merge(3, 1); // 3和1是亲戚    merge(1, 4); // 1和4是亲戚    cout << getFather(3) << endl; // 输出3的团伙代表人+换行    cout << query(3, 1) << endl; // 输出3和1是否是亲戚+换行}并查集巧妙吧!我们既没有构建图,也没有构建边,自始至终只用到了f数组,又优化了时间 。
不要小瞧并查集代码短,在很多时候并查集都会派上用场,比如著名的克鲁斯卡尔算法,就是通过并查集判断两个顶点是否相连的 。更重要的是体会并查集的思想,用这种思想来优化代码 。





推荐阅读