并查集:
-
: 查找x属于哪个集合,如果x属于某一个集合,则返回该集合的代表。
-
:如果元素 与元素 ,分别属于不同的集合,则将两个集合合并,否则不操作。
并查集基础操作:初始化
void makeSet(int n){
for(int i=1;i<=n;i++) dad[i]=i;
}
并查集基础操作:合并
只需要将每个集合的代表进行链接即可
void unionSet(int x,int y){
dad[findSet(x)]=findSet(y);
}
并查集基础操作:查询
int findSet(x){
if(dad[x]==x) return x;
else return findSet(dad[x]);
}
并查集查询优化 : 路径压缩
其实就是因为一个父节点他后面的儿子是很长的(大概),所以就把他弄成一排,这样深度就没有那么深,查询起来就很快
int findSet(x){
if(dad[x]==x) return x;
else return dad[x]=findSet(dad[x]);
}
并查集合并优化:按秩合并
就是也是把深度压缩,就是比如有两颗树,没必要把一棵树放在另一颗树的上面。
看下面这个图:
那个8如果这样放:
其实就很没必要,所以把那个8放在下面:
就像这样:
你会发现深度就变少了,虽然优化了一点,但是还是没优化多少,把路径压缩这个记住就行
另附干货: