CSU 2125小Z的培养皿(并查集)

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;
}

猜你喜欢

转载自blog.csdn.net/qq_36258516/article/details/80500815