PAT 甲级 1118 Birds in Forest

题意:给定一些照片,照片上面有一些树,树上有一些小鸟,判断最大的数的颗树可能有多少棵以及鸟有多少只;

思路:此题主要考察并查集,用一个数组保存信息,下标为节点的数据,值为节点的父节点,用一个访问数组标识该节点是否遍历到过,用于计算多少只,最后数组中访问过的节点而且值为负表示为根节点,根节点有多少个表示数就有多少棵;

如果并查集的概念不是很清楚的,建议先去看看并查集的概念,推荐看姥姥的mooc视频,此题涉及到了姥姥说的一些问题以及一些解决的方法,比如数的高度一直长高的问题如何解决,以及对如何加快对根节点的查找效率等问题;

代码:

#include<iostream>
#include<algorithm>
using namespace std;
int s[10010];
bool vis[10010] = {false};
int find(int x){
	if (s[x] < 0)return x;
	else {
		return s[x] = find(s[x]);//路径压缩,返回值的时候顺便更新所有的路径上的根节点
	}
}
void Union(int id1,int id2) {
	int root1 = find(id1);//当并的时候检查两个时候已经属于一个集合,不属于一个集合就合并两个节点
	int root2 = find(id2);
	if (root1 != root2) {//当两个根节点的不相同的时候,就进行合并
		if (s[root2] < s[root1]) {//第二个子树规模比第一个大,根节点的值为负表示无父节点,绝对值为以该节点为根节点的树的节点个数
			s[root2] += s[root1];
			s[root1] = root2;//把节点个数少的并到节点个数大的数中去
		}else {
			s[root1] += s[root2];
			s[root2] = root1;
		}
	}
}
int main() {
	fill(s, s + 10010, -1);//首先初始化,默认所有的节点认为自己是根节点
	int n, k, first, tem, quiry, maxtree = 0, maxbirds = 0,id1, id2;;
	cin >> n;
	for (int i = 0; i < n; i++) {
		scanf("%d%d",&k,&first);
		if (vis[first] == false)vis[first] = true;
		for (int j = 0; j < k - 1; j++) {
			scanf("%d",&tem);
			if (vis[tem] == false)vis[tem] = true;
			Union(first,tem);
		}
	}
	cin >> quiry;
	for (int i = 1; i<=10010; i++) {//查找所有的树和鸟,图片中的鸟的个数可能超过了总的鸟的数目要限制
		if (vis[i] == true) {
			maxbirds++;
			if (s[i] < 0)maxtree++;
		}
	}
	cout << maxtree << " " << maxbirds << endl;
	for (int i = 0; i < quiry; i++) {
		scanf("%d%d",&id1,&id2);
		printf("%s\n", find(id1)== find(id2)?"Yes":"No");
	}
	system("pause");
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值