码迷,mamicode.com
首页 > 其他好文 > 详细

并查集

时间:2018-09-21 20:28:24      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:scanf   clu   ++i   return   ace   节点   strong   不同类   temp   

处理何种问题:就我目前对于并查集的理解来说,并查集是一种很巧妙的数据结构,他可以将根据集合内各个元素之间的关系将其划分为几个不同类别。

 

性能:目前还没有直观感受,时间复杂度主要看测试数据的复杂程度。

 

原理:数据结构

 

实现步骤:while(root!=pre[root])     root=pre[root];    线索遍历的巧妙之处

 

备注:代码的的核心是FiFa(); 和 根节点之间的归并。

 

输入样例解释

5 3// n节点个数,m同一组的描述个数

1 2//节点1和节点2属于同一组

2 3

4 5

 

5 1

2 5

 

输出样例解释

2 //第一组样例一共可以分为两个大的类别

4

 

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MaxN=10010;
int pre[MaxN];
int n,m;

int FiFa(int root)
{
    int son,temp;
    son=root;
    while(root!=pre[root])//第一遍,提前寻找好根节点
        root=pre[root];

    while(son!=pre[son])//第二遍,将之前以前的根节点更新
    {
        temp=son;
        son=pre[son];
        pre[temp]=root;
    }
    return root;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<=n;++i)   pre[i]=i; //初始赋值,将每个点的根节点赋值为自己

        int ans=n;

        while(m--)
        {
            int a,b,root1,root2;
            scanf("%d%d",&a,&b);
            root1=FiFa(a);
            root2=FiFa(b);
            if(root1!=root2)
            {
                --ans;//一共有多少种互不相关的集合
                if(root1<root2)//个人比较喜欢让较小的当父亲节点,其实可以不用考虑大小
                    pre[root2]=root1; //针对于根节点和根节点的合并,不是是子节点的合并
                else
                    pre[root1]=root2;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

  

并查集

标签:scanf   clu   ++i   return   ace   节点   strong   不同类   temp   

原文地址:https://www.cnblogs.com/l1l1/p/9688168.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!