菜鸡学习之路之并查集

  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就当给自己记个笔记以后看了。

                          

原文地址:https://www.cnblogs.com/wushengyang/p/9118977.html