题目大意:
[USACO11OPEN]Learning Languages
题目描述:
农夫约翰的N ( 2 < = N < = 10 , 000 ) 只奶牛标号为1.. N,同样的有M ( 1 < = M < = 30 , 000 ) 种牛语标号为1.. M,第i只奶牛会说K i ( 1 < = K i < = M )种牛语,分别为L i 1 , L i 2 , … , L i K i ( 1 < = L i j < = M ) ,农夫的奶牛不是特别聪明,所以K i的累加和不大于100 , 000。两只奶牛只有当他们至少有一门语言一样的时候才可以沟通。否则这两只奶牛就需要别人来帮他们翻译才能交流。换句话说,A和B要进行沟通,他们可以通过T 1 , T 2 , … , T k来传递,比如A和T 1 , T 1 和T 2 , … , T k 和B进行交流。
农夫希望他的奶牛可以多多沟通,所以他买了很多课本去教她的奶牛语言。当然农夫非常的吝啬,他希望买最少的书就可以让所有的奶牛可以交流。你的任务就是帮他算出最少需要买几本书。
输入格式:
第一行输入两个整数N和M,表示N头牛和M种语言第二行到第N+1行,每一行第一个数K i 代表会的语言个数,而后K个是语言编号
输出格式:
算出最少需要买几本书。思路:
把每头牛的语言看作一个集合,当有交集的时候就可以并,在输入的时候一个一个并集就好了,不需要判断两头牛语言有没有交集。遍历每种语言的头统计一共有几个独立的集合,因为一个集合的头是一样的,所以开一个map储存是否已经遍历过这个头,如果没有加一即可,最后统计的集合数减一就是答案了。
code:
#include<bits/stdc++.h>
using namespace std;
int fa[100010];
int find(int x)//查找
{
if(fa[x]==x)return x;
else fa[x]=find(fa[x]);
return fa[x];
}
void unionn(int a,int b)//并集
{
int zi=find(a),fu=find(b);
fa[zi]=fu;
}
void inti(int n)//初始化
{
for(int i=1;i<=n;i++)
fa[i]=i;
}
int main()
{
map<int,bool>mp;
map<int,bool>cz;
int n,m,k;
cin>>n>>m;
inti(m);
int ans=0;
for(int i=1;i<=n;i++)
{
int a,b;
cin>>k;
if(k==0)
ans++;
cin>>a;
mp[a]=true;
for(int j=2;j<=k;j++)
{
cin>>b;
mp[b]=true;
unionn(a,b);
}
}
for(int i=1;i<=m;i++)
{
if(mp[i] && !cz[find(i)])
{
ans++;
cz[find(i)]=1;
}
}
cout<<ans-1;
}

京公网安备 11010502036488号