题意:
一个村子,有n个村民,有m种语言;
两个人想要交流,可以是他们会同一种语言,或者有个中间翻译,就是会他们两个人会的语言;
一个人学一门新的语言要花费一个能量;
问要想任意两人都可以交流,要花费多少能量;
思路:
如果一个村民会k种语言,就把这k种并起来,说明会这些语言可以互相交流;
然后统计在所有出现过的语言中有几个集合(注意是出现过的语言)
如果一个村民一门语言都不会,那至少要先花费一个能量学一门;
如果所有村民都是一门语言都不会,那答案就是n;
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 105;
int p[N], vis[N], viss[N], n, m, k;
void init() {
for(int i = 0; i <= n; i++) {
p[i] = i;
vis[i] = 0;
viss[i] = 0;
}
}
int findp(int x) {
return p[x] == x ? x : p[x] = findp(p[x]);
}
void Union(int x, int y) {
int u = findp(x);
int v = findp(y);
if(u != v)
p[u] = v;
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
int ans = 0,sum = 0;;
scanf("%d%d",&n,&m);
init();
for(int i = 0; i < n; i++) {
scanf("%d",&k);
int tmp;
if(k != 0) {
sum++;
scanf("%d",&tmp);
vis[tmp] = 1;
}else {
ans++;
}
for(int j = 1; j < k; j++) {
int tmp2;
scanf("%d",&tmp2);
vis[tmp2] = 1;
Union(tmp, tmp2);
}
}
for(int i = 1; i <= m; i++) {
if(vis[i] && !viss[findp(i)]) {
ans++;
viss[findp(i)] = 1;
}
}
if(sum == 0) {
ans = n + 1;
}
printf("%d\n",ans - 1);
}
}