并查集(路径压缩 + 启发式合并 + 非递归)
问题引入:
若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系?
先说明一下并查集的概念:(以下摘抄于 OI wiki https://oi-wiki.org/)
并查集是一种树形的数据结构,顾名思义,它用于处理一些不交集的 合并 及 查询 问题。 它支持两种操作:
查找(Find):确定某个元素处于哪个子集;
合并(Union):将两个子集合并成一个集合。
以下给出简单代码
for(int i=1;i<=n;i++) father[i]=i; //初始化
int find(int x) //简单查找 { if(x==father[x]) return x; return father[x]=find(father[x]); //路径压缩 }
int find2(int x) //非递归并查集 { int k=x,w; while(father[x]!=x) x=father[x]; while(father[k]!=k) { w=father[k]; father[k]=x; k=w; } return x; }
void unionSet(int x, int y) //启发式合并 { int xx = find(x), yy = find(y); if (xx == yy) return; if (siz[xx] > siz[yy]) swap(xx, yy); father[xx] = yy; siz[yy] += siz[xx]; }
一些题目:
模板(https://www.luogu.com.cn/problem/P3367)
亲戚 (https://www.luogu.com.cn/problem/P1551)
食物链(https://www.luogu.com.cn/problem/P2024)
浙公网安备 33010602011771号