第一次学比较玄学,反正本蒟蒻听出了脑雾现象,后来慢慢接受了,感jio也没那么难(对我来说)。
Q:什么是并查集?
A:我也不知道,因为比较玄学(emm…),其实类似于数学里的集合。
并查集的两种方式
一种朴素的。
一种路径压缩的。
(当时上课划水导致朴素的根本不会,所以本蒟蒻直接学的路径压缩?)
废话不多说,上代码
int find(int x) { return fa[x]=x?x:fa[x]=find(fa[x]); }
用了一个三目运算符,不懂的去百度一下,也不难。
首先我们有一些元素,我们要把他们合并,那开始就令各个元素的父亲是自己
for(re int i=1;i<=n;i++){ fa[i]=i; }//就可以了
然后模拟一下找爹合并的过程(借用别的文章的图)
parent[i]指向的是i的父亲的节点,
假设我们起始的并查集如上图所示,现在我们要find[4],首先我们根据parent[4]可以得出,4并不是一个根节点,因此,我们可以在向上继续查询之前,把这个节点往上面挪一挪(路径压缩),首先现在4节点连接到其父亲3节点上,我们可以让4节点不在指向3节点作为父亲节点了,而是让其跳一下,让其指向2节点(即父亲节点的父亲节点)作为新的父亲节点。
这样,我们就发现树的层数由原来的5层变成了现在的4层,即路径被压缩了一下。
递归实现这一过程,使得4的根节点直接指向0,同样4的父节点,4父节点的父节点(这么套娃一直套到根节点)…,最终变成这样:
不明白递归细品一下就明白了,fa[i]一直向前指,指到根节点回溯(这么说也没问题),回溯什么呢?
fa[x]=find(fa[x]) ———>回溯这个; 到根节点之后, find(fa[x]) 指的就是根节点,所以一直归回去就得出了x的根节点,判断联通比较根节点是否为同一个就好了