合根植物

该博客介绍了如何运用并查集解决2017年蓝桥杯国赛中的一道题目。题目背景是在一个w星球的种植园里,植物的根可能会连在一起,要求计算共有多少株合根植物。博主通过详细解析输入输出样例,阐述了利用并查集实现找根节点和合并操作的思路,并给出了C++代码实现。通过输入数据的处理和查找根节点,最后统计不同的根节点数量作为答案。
摘要由CSDN通过智能技术生成

题目描述

题目来源:2017蓝桥杯国赛

w 星球的一个种植园,被分成 m×n个小格子(东西方向 m 行,南北方向 n 列)。每个格子里种了一株合根植物。

这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。

如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?

输入描述

第一行,两个整数 m,n,用空格分开,表示格子的行数、列数(1≤m,n≤1000)。

接下来一行,一个整数 k (0≤k≤10^5 ),表示下面还有 k 行数据。

接下来 k 行,每行两个整数 a,b,表示编号为 a 的小格子和编号为 b 的小格子合根了。

格子的编号一行一行,从上到下,从左到右编号。

比如:5×4 的小格子,编号:

1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
17 18 19 20

 

输出描述

输出植物数量。

输入输出样例

示例

输入

5 4
16
2 3
1 5
5 9
4 8
7 8
9 10
10 11
11 12
10 14
12 16
14 18
17 18
15 19
19 20
9 13
13 17

 

输出

5

 

样例说明

其合根情况参考下图:

运行限制

  • 最大运行时间:2s
  • 最大运行内存: 256M

思路:

1. 使用并查集解决问题;用一个数组ab(每个元素都初始化为其下标,即最初每个数指向自己,或者说父亲结点为自己)来存放输入的两个整数a、b之间的关系;如ab[x]=y;表示x指向y,或者说x的父亲结点为y;

2. 对于每一组输入a、b;通过find()函数分别寻找其指向的结点(即父亲结点)fa和fb,若a,b有共同的父亲,即fa=fb,则不作操作,否则将a、b和为一体,可以把fa指向fb(即fb为fa的父亲结点),也可以把fb指向fa(即fa为fb的父亲结点);

3. 找出所有结点的的根结点(即父亲结点的父亲结点……直到没有父亲结点的那个结点),然后统计根结点的数目即为最终答案(每个根结点和直接或者间接指向自己的结点算是一株植物);

 

//2017g 合根植物     vxgzh:xtsn
#include <iostream>
using namespace std;
#include <set>
#define N 1005

int ab[N*N]={0};   //存放的是父节点 

int find(int a)
{
	if(ab[a]==a)   //a指向它自己 ,即a的根是自己 
		return a;
	else
		return ab[a]=find(ab[a]);    //a的根是find(ab[a]),并作修改 
}
int main()
{ 
	int n,m,k,a,b;	
	cin>>n>>m; 
	for(int i=1;i<=n*m;i++)   //父节点的初始化 
		ab[i]=i;		
	cin>>k;
	for(int i=0;i<k;i++)
	{
		cin>>a>>b;
		int fa = find(a);   //找到a的根 fa 
		int fb = find(b);   //找到b的根 fb
		if(fa!=fb)    //没有共同的根 
	            ab[fa]=fb;      //  ab[fb]=fa;也可以 
	//将a的根fa指向b的根fb,即把a的根fa的根(原来fa的根为它自己)修改fb;		
	}
	set <int> se;
	for(int i=1;i<=n*m;i++)
		se.insert(find(i));   //找到每个结点的根; 

	cout<<se.size()<<endl;   //不同根的数量 
		
	
	return 0;
}

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值