A - Learning Languages
在 “BerCorp” 公司,有 n 名雇员。这些雇员可以使用 m 种核准的正式语言,用于正式的通信。这些语言以整数编号,介于 1 到 m 之间。对于每名雇员,我们已知他所懂语言的列表。这个列表可能是空的,即一名雇员可能不懂任何正式语言。但雇员们愿意学习一种或多种正式语言,只要公司为他们的课程而付费。对于每名雇员而言,学一门语言的课程费用是 1 BER$ 元 (berdollar)。
求出该公司需要花费的合计费用的最小值,使得任意一名雇员能够与任意其他一名雇员通信 (他们之间的通信可以是非直接的,即允许其他雇员帮助翻译)。
输入
第一行包含两个整数 n 和 m (2 ≤ n, m ≤ 100) — 雇员数目和语言数目。
接下来的 n 行 — 每个雇员的语言列表。在第 i 行的开始,是整数 ki (0 ≤ ki ≤ m) — 第 i 名雇员所懂语言的数目。接下来,第 i 行还包含了 ki 个整数 — aij (1 ≤ aij ≤ m) — 第 i 名雇员所懂各语言的相应标识。数据保证:每个列表中的全部标识都是唯一的。注意:一名雇员可能懂得 0 种语言。
各行中的数字,以单个空格间隔。
输出
打印仅有的一个整数 — 所需支付的费用的最小值,使得最终每名雇员可以与其他任何一名雇员通信 (其他雇员可以帮助翻译)。
示例
输入
5 5
1 2
2 2 3
2 3 4
2 4 5
1 5
输出
0
输入
8 7
0
3 1 2 3
1 1
2 5 4
2 6 7
1 3
2 7 4
1 1
输出
2
输入
2 2
1 2
0
输出
1
备注
在第二个示例中,雇员 1 可以学习语言 2,且雇员 8 可以学习语言 4。
在第三个示例中,雇员 2 必须学习语言 2。
题意:输入n,m代表人数和语言种数,接下来n行,输入t(每个人会的语言总数)后面跟着t个数(语言序号)问总共还要学习多少语言,可以让每两个员工可以直接或间接交流。
方法:并查集
#include"iostream"
#include"algorithm"
#include"cstring"
#include"set"
using namespace std;
int pre[150];
void init()
{
for(int i = 0;i < 101;i ++)
{
pre[i]=i;
}
}
int find(int x)
{
return x==pre[x] ? x:pre[x]=find(pre[x]);
}
void join(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx != fy)
{
pre[fx]=fy;
}
}
int main()
{
int n,m;
while(cin >> n >> m)
{
init();
int vst[105]={0};
int sum =0 ;
for(int i = 0;i < n;i ++)
{
int t;
cin >> t;
int a[105];
if(t==0)
{
sum ++;
continue;
}
cin >> a[0];
vst[a[0]]++;
for(int j = 1;j < t;j ++)
{
cin >>a[j];
vst[a[j]]++;
join(a[j-1],a[j]);
}
}
int pl = 0;
for(int i = 1;i <= m;i ++)
{
if(vst[i])
{
if(pre[i]==i)
{
pl++;
}
}
}
pl=max(0,pl-1);
cout<<sum+pl<<endl;
}
return 0;
}