POJ1611The Suspects并查集

31 篇文章 0 订阅
14 篇文章 0 订阅

并查集是一种用来管理元素分组情况的数据结构。并查集可以高效地进行如下操作。不过需要注意并查集虽然可以进行合并操作,但是却无法进行分割操作

·查询元素a和元素b是否属于同一组。

·合并元素a和元素b所在的组。

并查集的精髓(即它的三种操作,结合实现代码模板进行理解):

1、Make_Set(x) 把每一个元素初始化为一个集合

初始化后每一个元素的父亲节点是它本身,每一个元素的祖先节点也是它本身(也可以根据情况而变)。

2、Find_Set(x) 查找一个元素所在的集合

查找一个元素所在的集合,其精髓是找到这个元素所在集合的祖先!这个才是并查集判断和合并的最终依据。
判断两个元素是否属于同一集合,只要看他们所在集合的祖先是否相同即可。
合并两个集合,也是使一个集合的祖先成为另一个集合的祖先,具体见示意图

3、Union(x,y) 合并x,y所在的两个集合

合并两个不相交集合操作很简单:利用Find_Set找到其中两个集合的祖先,将一个集合的祖先指向另一个集合的祖先。

题目大意:SARS(非典型肺炎)传播得非常厉害,其中最有效的办法是隔离那些患病、和患病者接触的人。现在有几个学习小组,每小组有几个学生,一个学生可能会参加多个小组。小组中只要有一个人得病,其余的都是嫌疑人。现在已知这些小组的人员,且0号学生已经患病,求一共有多少个嫌疑人。

分析:每个小组的人员属于同一个集合。在根节点记录每个集合的个数num[i],然后找到0所属的根节点,num[findSet(0)]即为所有的嫌疑人数。

*#include <iostream>

using namespace std;

const int INF=1000000;

const int MAX_N=33333;

int par[MAX_N];  //父亲
int num[MAX_N];  //树的秩记录每个集合的节点个数
int rank[MAX_N]; //树的高度


//初始化n个元素
void init(int n){
    for (int i=0; i < n ; i++){
        par[i] = i; //使用本身做根
        num[i] = 1;
        rank[i] = 0;
     }
}

//查询树的根
int findroot(int x){
if(par[x] != x)
{
        return par[x] = findroot(par[x]);
    }
    return par[x];
}
//合并x和y所属的集合
void unite(int x,int y){
    x=findroot(x);
    y=findroot(y);
    if(x == y)  return;
if(rank[x] < rank[y])
{
        par[x] = y;
        num[y] += num[x];
} else
{
        par[y] = x;
        num[x] += num[y];
        if(rank[x] == rank[y]) rank[x]++;
    }
}
//判断x和y是否属于同一个集合
bool same(int x,int y)
{
    return findroot(x) == findroot(y);
}

int n,m;

int main()
{
    while(cin>>n>>m&&n)
    {
        int k,res,vis;
        init(n);
        while(m--)
        {
             cin>>k>>vis;
            for(int i=1;i<k;i++)
            {
                cin>>res;
                unite(vis,res);
            }
        }
        cout<<num[findroot(0)]<<endl;
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值