PAT 1118 C++ 版

本文详细解析PAT1118题目,采用C++实现并查集算法,解决图片中鸟的数量及同一树判断问题。通过实例演示并查集的初始化、查找与合并操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PAT 1118 C++

1.题意

给出每张图片中的鸟的数目,以及每只鸟的下标,求出树数。
同时查询两只鸟是否在同一棵树中。

2.分析
  • 使用并查集
  • 取鸟较小的索引的那个数作为那一组数据的根。
3. 测试用例
4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7

根据以上输入,得到的结果就是:

2 10
Yes
no
4.代码
#include<cstdio> 
#include<cstring>
#include<cmath> 
#include<algorithm>
#include<map>
#define maxn 10002
using namespace std;

//所有节点的父节点 
int father[maxn];

//find the father node of a 
int findFather(int a){
	while(a != father[a]){
		a = father[a];
	}
	return a;
}

int unionFather(int a,int b){
	//分别找出节点a,b的父节点 
	int fa = findFather(a);
	int fb = findFather(b);
	father[max(fa,fb)] = min(fa,fb); 
}

int main(){
	int N;
	scanf("%d",&N);//the picture Num 
	int k;//the number of birds in this picture
	int i,j;
	int birdAll [maxn]; //all birds
	int birdNum = 0;//total birds number 
	int curBird;//the index of current bird
	int birdRow[maxn];// every input row of bird
	map<int,int> record;
	//init 
	for(i = 0;i< maxn;i++){
		father[i] = i;
	}
	//input
	for(i = 0;i< N ;i++){
		scanf("%d",&k);
		for(j = 0;j < k;j++){
			scanf("%d",&curBird);//输入鸟的下标 
			birdRow[j] = curBird;
			if(birdAll[curBird] == 0){
				birdNum ++;
				birdAll[curBird] = curBird;
			}
		}
		//将当前行的bird 合并到一起 
		for(j = 1;j < k;j++){
			unionFather(birdRow[0],birdRow[j]);
		}
	}
	
	int birdHerd = 0;//鸟群数 
	//是否需要遍历所有节点,才能得出鸟群数? 	
	int tempRoot = 0; 
	for(i = 1;i <= maxn - 1 ;i++){		
		if(birdAll[i] == i)
		{
			tempRoot = findFather(birdAll[i]);
		}
		if(record.find(tempRoot) == record.end()){
			birdHerd ++;		
			record[tempRoot] = 1;			
		}
	}
	
	//printf("birdHerd = %d,birdNum = %d\n",birdHerd,birdNum);
	printf("%d %d\n",birdHerd,birdNum);
	int queryNum ;
	scanf("%d",&queryNum);
	int b1,b2;
	int fb1,fb2;	
	for(i = 1;i<= queryNum ;i++){
		scanf("%d %d",&b1,&b2);
		fb1 = findFather(b1);
		fb2 = findFather(b2);
		
		if(fb1 == fb2){
			printf("Yes\n");
		}
		else{
			printf("No\n");
		}		
	}			
}
5.执行结果

在这里插入图片描述

6.总结

感觉pat题还是很经常考并查集的。一定要熟悉!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说文科技

看书人不妨赏个酒钱?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值