emmm第一次写博客就随便写写了,开始才学习并查集,全当给自己以后忘记之后做个笔记方便复习(预习)了。
参照大佬精细讲解把自己学习理解的给写出来了。写的不好不要介意(捂脸
根据大佬们的博客叙述,并查集用来求连通图之类的,给定一堆数字,以及这些数字两两之间的关系,则可以用线把他们连接起来,随着一条线一条线的连接起来,则很多关系都一目了然了。若两个数字之间有线连起来了(不管几条线),则说明这些数字是处于联通状态的。
对于一个问题,要理解题目意思,比如连通性这样的,搞清楚题目要的意思是什么
比如:
1. 给出两个节点,判断它们是否连通,
如果连通,不需要给出具体的路径
2. 给出两个节点,判断它们是否连通,
如果连通,需要给出具体的路径
对于第一个问题而言,判断联通则可以使用并查集,只需两个节点之间有路径可走就可以了。
对于第二个问题而言,不但需要判断节点是否联通,还需要找到这个节点走到那个节点的路径,所以选择dfs什么的可能才正确。
如何解决问题
就本菜鸡来说,大佬的那些代码根本看不懂,只能在hdu水水并查集的题目这样子,所以只能写写数这种思路。
比如hdu1213这种入门级。对于解决这一类问题的话,可以认为,节点一但联通了,就可以看做是一个组的,而不联通的就属于另外一个组,最后可以再统计组的个数之类的。对于两个输入的节点,可以首先判断他们所属的组是不是相同,如果相同,则说明这两个节点是联通的;如果不相同,则说明这两个节点不连通。所以为了方便,先对每个数字进行预处理,即刚开始每个节点都是自己单独有一个组,或者说每个人初始的father都是他自己。
for(int i=0;i<n;i++) { father[i]=i; }
///先令它们属于各自不同的集合,每个人的父节点都是它们自己
对于每个节点i,它的组号也是i。
初始化结束后,然后定义一个函数来“寻根”。一般可以采用递归的方法来不断找寻自己的父节点直到找到根节点。
int find(int x)
{ if(x==father[x]) return x; else return find(father[x]); } ///采用递归的方法来不断寻找父节点
当处理完了后,就定义个函数将两个给定的合并起来。
void hebing(int a,int b) { int fa=find(a); int fb=find(b); if(fa!=fb) father[fa]=fb; } ///合并两个集合,找到a和b的根节点,如果根节点不同,就把其中一个的最高处的根节点的父亲设为另一个根节点
至此,就差不多处理完了。emmmmm就当给自己记个笔记以后看了。