PAT——1118 Birds in Forest 甲级

题目

https://pintia.cn/problem-sets/994805342720868352/problems/994805354108403712

题意

一幅画里的鸟都是同一棵树上的,输出树和鸟的数量,并判断给定的两只鸟是否在同一棵树上

代码解析

本题运用了并查集,但有以下几点需要注意:

首先我需要解释一下这行代码:else return pre[x]=find(pre[x]);
这句是先把find到的x赋值给pre[x]的,查找路径上的每个点,下一次找的时候,就能直接找到终点了;再解释一下就是因为此函数找到根节点就返回,所以所有的节点在递归的赋值中最终都指向了根节点,为后续的Find节约了时间

其次是这行代码:int t=find(i);,如果两幅画有重合部分,那这两幅画的鸟应该都属于同一颗树,这行代码就是把同一棵树的子树合并起来(必须有)

最后,测试点给出的1到某个整数的节点并不一定是连续的,比如有可能是1 2 3 6 8,就跳过了4 5 7,所以后面的判断的基础就是这个数字要存在(vis[i])。虽然题目中有continuously,但不加vis好像就是错的,还是加一下比较好

AC代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=10005;
int pre[maxn];
unordered_map<int,int> vis;
int find(int x)
{
	if(x==pre[x]) return x;
	else return pre[x]=find(pre[x]);//路径压缩 
}
void combine(int a,int b)
{
	int x=find(a),y=find(b);
	if(x!=y) pre[y]=x;
}
int main()
{
	int n,m,k,x,y;
	for(int i=1;i<=maxn;i++) pre[i]=i;
	cin>>n;
	while(n--)
	{
		cin>>m>>x;
		vis[x]=1;
		for(int i=0;i<m-1;i++)
		{
			cin>>y;
			vis[y]=1;
			combine(x,y);	
		}	
	} 
	int cnt1=0,cnt2=0;
	for(int i=1;i<=maxn;i++)
	{
		if(vis[i])
		{
			cnt2++;
			int t=find(i);//这步必须有,这是为了合并同一棵树的子树 
		}
	}
	for(int i=1;i<=maxn;i++)
	{
		if(vis[i])
		{
			if(pre[i]==i) cnt1++;
		}
	}
	cout<<cnt1<<" "<<cnt2<<endl;
	cin>>k;
	while(k--)
	{
		cin>>x>>y;
		if(find(x)==find(y)) cout<<"Yes"<<endl;
		else cout<<"No"<<endl; 
	}
}

参考

1118. Birds in Forest (25)-PAT甲级真题(并查集)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值