CSU 2125

https://blog.csdn.net/qq_36258516/article/details/80500815

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
1
2
3
4
5
6
7
8
9
10
Sample Output
2
2
1
2
题意
  给出n个培养皿,每个培养皿里面有k种细菌,如果两个培养皿包含相同的至少一种相同的细菌,那么他们可以合并,最后问至少需要几个培养皿。

解题思路
  根据题意,很容易就能想到并查集。每个培养皿都相当于是一个集合,如果含有相同的细菌,就直接把并查集合并。这个题也没必要建图,直接把每个培养皿中的第一个细菌作为父节点即可。最后再遍历每个父节点(父节点的p[x]==x)做并查集,如果查询结果是他本身,就需要一个培养皿,累加即可得出结果。

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e5+5;

set<int> s;
int pa[maxn];

int findSet(int x){
    return pa[x]==x? x:pa[x]=findSet(pa[x]);
}

int main(){
    //freopen("datain.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        s.clear();
        for(int i=0;i<maxn;i++)
            pa[i]=i;
        for(int i=0;i<n;i++){
            int k;
            scanf("%d",&k);
            int x,y,tmp;
            for(int j=0;j<k;j++){
                scanf("%d",&tmp);
                if(j==0){
                    x=findSet(tmp);
                    s.insert(tmp);
                }
                else{
                    y=findSet(tmp);
                     pa[y]=x;
                }
            }
        }
        int ans=0;
        for(set<int>::iterator it=s.begin();it!=s.end();++it){
            if(findSet(*it)==(*it)) ans++;
        }
        printf("%d\n",ans);
    }
}

猜你喜欢

转载自blog.csdn.net/hanker99/article/details/88396740
今日推荐