1611 The Suspects:新冠肺炎来了!并查集简单使用+并查集基础附送

题目大意

题目链接
严重急性呼吸道综合症(SARS)是一种病因不明的非典型肺炎,在2003年3月中旬被认为是全球性威胁。为了最大程度地减少向他人的传播,最好的策略是将嫌疑犯与其他人分开。

在不蔓延疾病大学(NSYSU)中,有很多学生团体。 同一组中的学生经常互相交流,一个学生可以加入多个组。 为了防止可能的SARS传播,NSYSU收集所有学生团体的成员列表,并在其标准操作程序(SOP)中制定以下规则。

一旦组中的某个成员成为可疑对象,该组中的所有成员都将成为可疑对象。

但是,他们发现,当一个学生被确认为犯罪嫌疑人时,要识别所有犯罪嫌疑人并不容易。 您的工作是编写一个找到所有嫌疑犯的程序。

输入

输入文件包含几种情况。 每个测试用例都以一行中的两个整数n和m开头,其中n是学生数,m是组数。 您可以假设0 <n <= 30000并且0 <= m <=500。每个学生都用0到n-1之间的唯一整数编号,并且最初在所有情况下,学生0都被视为犯罪嫌疑人。 该行之后是组的m个成员列表,每组一行。 每行以一个整数k开头,该整数k代表组中成员的数量。 在成员数之后,有k个整数表示该组中的学生。 一行中的所有整数至少间隔一个空格。

n = 0和m = 0的情况表示输入的结尾,无需处理。

思路分析

我最喜欢的并查集小水题,

#include<iostream>
#include<string.h>
using namespace std;

#define MAX 30005
#define ll long long

ll n, m, kind[MAX], a, b, t;

ll find(ll a) {
	if (a == kind[a])return a;
	else return kind[a] = find(kind[a]);
}

void unite(ll a, ll b) {
	kind[find(a)] = kind[find(b)];
}
int main() {
	while (cin >> n >> m && n + m != 0) {
		ll res = 1;
		for (int i = 0; i < n; i++)kind[i] = i;
		while (m--) {
			cin >> a >> b;
			ll t = b;
			//第一个输入的为基础
			for (int i = 0; i < a - 1; i++) {
				cin >> b;
				unite(b, t);
			}
		}
		for (int i = 1; i < n; i++) {
			if (find(i) == find(0)) res++;
		}
		cout << res << endl;
	}
}
发布了211 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/csyifanZhang/article/details/105300194