(并查集)求给定图G的连通分量的数目

来源:互联网 发布:云数据库怎么和安卓 编辑:程序博客网 时间:2024/06/05 04:48

本总结是是个人为防止遗忘而作,不得转载和商用。

题目

         求给定图G的连通分量的数目。

         如:某国家有N个小岛组成,经过多年的基础设施积累,若干岛屿之间建立了若干桥梁。先重新完善该国的行政区划,规定只要有桥梁连接的岛屿则归属同一个城市(可以通过其他岛屿中转),问该国一共多少个城市?

方法一:深度优先搜索

         随便选一个点,搜完后如果有未访问的点就从未访问的点中选一个再搜,重复上述过程。重复了几次就有几个连通分量。

方法二:并查集

         其实对于该题这样的都可以归为下面这样的形式:

                   1,i和i一定属于同一类

                   2,若i和j属于同一类,则j和i也属于同一类

                   3,若i和j属于同一类,而j和k属于同一类,则i和k也属于同一类

         而只要满足这样的形势,都可以想一想并查集。

什么是并查集

         嗯..这个不太好解释,直接看并查集怎么得出来的会更方便些。

         假设有6个节点:1,2,3,4,5,6。其中1,3,4是相互连接(或者说属于同一类)的,2和6是相互连接的,5自己一个。

         于是这样做并查:

                  1,一开始自己指向自己:1指向1,2指向2,。。。。

                  2,这里1和3互相连接,那么就从1和3中随便拿出一个指向另一个,如:令3指向1。

                  3,重复2,令4指向3;6指向2.

                  4,从每个集合中任取一个作为代表元素,然后数一下有多少个代表元素就OK了,如:1,3,4中令1为代表元素,2,6中令2为代表元素,5的代表元素是本身,于是1的代表元素是1,3的代表元素是1,4的代表元素是1,2的代表元素是2,6的代表元素是2,5的代表元素是5,一共有3个代表元素。

         话说上面第四步是4->3->1,不过因为到头来都是找代办元素,因此改成以1为根节点,4和3作为1的子节点更好,这样下次查找时就可以一下子就找到代表元素了。

         于是乎,有时候我们会遇到查找某个元素的代表元素,那直接用下面的代码就可以:

                   introot = i;

                   //查找 root

                   while( root != m_pParent[root] ) {

                            root= m_pParent[root];

                   }

                   //将所有的子结点都直接指向root

                   intt = i;

                   intp;

                   while(t != root ) {

                            p= m_pParent[t];  // 记录t的父节点

                            m_pParent[t]= root;  // t直接链到root

                            t= p;  // 沿着父节点继续向上找

                   }

0 0