并查集(一)

题目要求

新型冠状病毒肺炎(Corona Virus Disease 2019,COVID-19),简称“新冠肺炎”,是指2019新型冠状病毒感染导致的肺炎。
如果一个感染者走入一个群体,那么这个群体需要被隔离!
小A同学被确诊为新冠感染,并且没有戴口罩!!!!!!
危!!!
时间紧迫!!!!
需要尽快找到所有和小A同学直接或者间接接触过的同学,将他们隔离,防止更大范围的扩散。
众所周知,学生的交际可能是分小团体的,一位学生可能同时参与多个小团体内。
请你编写程序解决!戴口罩!!

Input
多组数据,对于每组测试数据:
第一行为两个整数n和m(n = m = 0表示输入结束,不需要处理),n是学生的数量,m是学生群体的数量。0 < n <= 3e4 , 0 <= m <= 5e2
学生编号为0~n-1
小A编号为0
随后,m行,每行有一个整数num即小团体人员数量。随后有num个整数代表这个小团体的学生。

Output
输出要隔离的人数,每组数据的答案输出占一行。

求解思路

使用并查集存储学生所在团体的信息,为了降低查找根节点的时间,查询根结点的函数如下:

int find(int x)
{
	if (fa[x] == x)
		return x;
	return fa[x] = find(fa[x]);
}

每次查询,fa中的值都会被更新。
为了保证同一团体有且只有一个共同的根结点,合并函数如下:

void unio (int x, int y)
{
	if (x > y)
		swap(x, y);
	if (x != y)
	{
		fa[y] = x;
		ranked[x] = ranked[x] + ranked[y];
	}
}

注意union是c++的关键字,不能使用。选取小的结点作为根节点,若x>y,使用swap函数将x,y交换。注意unio的参数是两个团体的根结点。
ranked数组记录团体中学生数量。

代码
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;

int n, m;
int fa[30005];
int ranked[30005];
int find(int x)
{
	if (fa[x] == x)
		return x;
	return fa[x] = find(fa[x]);
}
void unio (int x, int y)
{
	if (x > y)
		swap(x, y);
	if (x != y)
	{
		fa[y] = x;
		ranked[x] = ranked[x] + ranked[y];
	}
}
int main()
{
	while (1)
	{
		cin >>n>> m;
		if (n == 0 && m == 0)
			break;
		for (int i = 0; i < n; i++)
		{
			fa[i] = i;
			ranked[i] = 1;
		}
		for (int i = 0; i < m; i++)
		{
			int num;
			cin >> num;
			int first;
			cin >> first;
			for (int j = 1; j < num; j++)
			{
				int temp;
				cin >> temp;
				unio(find(first), find(temp));
			}
		}
		cout << ranked[find(0)] << endl;
	}
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值