bzoj 3296: [USACO2011 Open] Learning Languages

简述题意:

农夫约翰的N(2<=N<=10,000)只奶牛标号为1..N,同样的有M(1<=M<=30,000)种牛语标号为1..M,第i只奶牛会说K_i(1<=K_i<=M)种牛语,分别为L_i1,L_i2,…,L_{iK_i}(1<=L_ij<=M),农夫的奶牛不是特别聪明,所以K_i的累加和不大于100,000。

两只奶牛只有当他们至少有一门语言一样的时候才可以沟通。否则这两只奶牛就需要别人来帮他们翻译才能交流。换句话说,A和B要进行沟通,他们可以通过T_1,T_2,…,T_k来传递,比如A和T_1,T_1和T_2,…,T_k和B进行交流。

农夫希望他的奶牛可以多多沟通,所以他买了很多课本去教她的奶牛语言。当然农夫非常的吝啬,他希望买最少的书就可以让所有的奶牛可以交流。你的任务就是帮他算出最少需要买几本书。

难度:NOIP-

算法:并查集

题解:

对于每头牛,把他自己与他会的语言连边即可。

利用并查集,进行查找。

但是,luogu #1数据有问题,#1是样例,后面的测试数据output只有       “最少需要买几本书”

代码如下:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#define ll long long
#define N 10005
#define M 30005
using namespace std;
int fa[N+M];
int vis[N];
int findf(int x)
{
	if(x==fa[x]) return x;
	return fa[x]=findf(fa[x]);
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	for(int i = 1;i <= n+m;i++)
	{
		fa[i]=i;
	}
	for(int i = 1;i <= n;i++)
	{
		int c;
		scanf("%d",&c);
		for(int j = 1;j <= c;j++)
		{
			int x;
			scanf("%d",&x);
			int t1=findf(x+n);
			int t2=findf(i);
			if(t1!=t2) fa[t1]=t2;
		}
	}
	for(int i = 1;i <= n;i++) vis[findf(i)]=1;
	int ans=0;
	int a,b;
	for(int i = 1;i <= n;i++)
	{
		if(vis[i]) ans++;
	}
	printf("%d\n",ans-1);
	return 0 ;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值