CSU 2125小Z的培养皿(并查集)
Description
小Z高中的时候特别喜欢生物,在一次做实验的过程中,小Z配置了n个培养皿,每个培养皿中有着若干种类的细菌,但由于实验室的培养皿数量有限,老师要求小Z尽可能少地使用培养皿。为此,小Z只得将一些培养皿进行混合,但由于一些生物上的特殊要求,只有含有相同细菌的培养皿才能混合,否则细菌将全部死亡。这时候小Z想请求你——CSU(California State University)最厉害的编程高手,希望你帮忙解答出至少需要多少培养皿。
Input
第一行为T(T ≤10),表示有T组数据。
每一组数据首先是一个正整数n(1 ≤ n ≤ 1000),
接下来n行,每行首先一个数k,表示这一个培养皿中有k(1 ≤ k ≤ 100)种细菌,
接下来k个数,a_1,a_2,…,a_k,(1 ≤ a_i ≤100000)。
每个数代表一种细菌的编号,编号之间通过空格隔开,培养皿中的细菌均不相同。
Output
输出最少需要的培养皿数量,每组数据的答案占一行
Sample Input
2
3
3 1 2 3
3 3 9 7
3 4 5 10
4
1 1
3 1 2 3
1 4
4 8 7 4 5
Sample Output
2
2
题意
给出n个培养皿,每个培养皿里面有k种细菌,如果两个培养皿包含相同的至少一种相同的细菌,那么他们可以合并,最后问至少需要几个培养皿。
解题思路
根据题意,很容易就能想到并查集。每个培养皿都相当于是一个集合,如果含有相同的细菌,就直接把并查集合并。这个题也没必要建图,直接把每个培养皿中的第一个细菌作为父节点即可。最后再遍历每个父节点(父节点的p[x]==x)做并查集,如果查询结果是他本身,就需要一个培养皿,累加即可得出结果。
代码
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<map>
#include<set>
#include<queue>
using namespace std;
const int maxn = 1e5+5;
set<int> s;
int p[maxn];
int find(int x)
{
return p[x]==x?x:p[x]=find(p[x]);
}
int main()
{
// freopen("in.txt","r",stdin);
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=0; i<=maxn; i++)
p[i]=i;
s.clear();
for(int i=0; i<n; i++)
{
int k,x,y,tmp;
scanf("%d",&k);
for(int j=0; j<k; j++)
{
scanf("%d",&tmp);
if(j==0)
{
x=find(tmp);
s.insert(tmp);
}
else
{
y=find(tmp);
if(x!=y) p[y]=x;
}
}
}
int ans=0;
for(set<int>::iterator it=s.begin(); it!=s.end(); it++)
{
if(find((*it))==(*it))
ans++;
}
printf("%d\n",ans);
}
return 0;
}