并查集小结
并查集就是一个可以连通一块东西的工具。
基础:
这么理解吧,有一堆亲戚,每次给你两个人,告诉你他们是亲戚,最后任意给你两个人,问他们是不是亲戚。
这个时候,并查集就大显神通了。我们可以每次输入两个数,如果这两个数不在一块,把这两个数连接起来,到了最后,不就是变成了一棵树了吗?最后查询时,每次看他们是不是在一棵树上就行,也就可以查询他们的根是不是一样的。
并查集实现的就是大概这样一个功能,下面给出代码:
查找:
int find(int x){
if(fa[x] != x) return find(fa[x]);
else return x;
}
合并:
void un(int x , int y){
int xx = find(x) , yy = find(y);
fa[xx] = yy;
}
\(fa[i]\)就是指某一个节点的父亲,对其初始化时肯定是\(fa[i]=i\),指向自己。
优化
可是,有的时候,这条链会被拉的很长,像这样:
很长的链~
这样往上搜索时,会很耗费时间,这个时候怎么办呢,优化:
路径压缩:
因为我们只用找到他们的根节点就可以看他们是不是一起的了,为何不让他们都直接指向根节点呢?像这样:
很短的链~
这样过后,查找时间就变短了,合并的代码肯定就不变了,下面给出查找的代码:
int find(int x){
if(x == fa[x]) return x;
else return fa[x] = find(fa[x]);
}
总结:其实优化还有一种方法,叫按秩合并,但是优化作用没路径压缩大,也不太好写,只有路径压缩就已经够了嗐就是不会而已。
亿道并查集联系题:奶酪