蓝桥杯:历届试题 合根植物 和INF的巧妙取值

下面是题干:
问题描述

w星球的一个种植园,被分成 m * n 个小格子(东西方向m行,南北方向n列)。每个格子里种了一株合根植物。
  这种植物有个特点,它的根可能会沿着南北或东西方向伸展,从而与另一个格子的植物合成为一体。

如果我们告诉你哪些小格子间出现了连根现象,你能说出这个园中一共有多少株合根植物吗?
输入格式
  第一行,两个整数m,n,用空格分开,表示格子的行数、列数(1<m,n<1000)。
  接下来一行,一个整数k,表示下面还有k行数据(0<k<100000)
  接下来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
样例说明
  其合根情况参考下图

前言:刚开始看这个题,我以为是深度搜索,因为刚学的深度搜索里面有一个类似的题目。然后仔细看了看发现这个题挺简单的,就是需要标记一下下标和前面的元素的关系。大概有了思路,但是实现起来很难。后来,看了别人的代码,才知道这里需要用到并查集,如果不知道这个知识的话可以提前去看一下。这里用到了它的合并,查找的操作。
另外,这个题看似是二维的但其实是一维的(因为有编号),我看有的人申请了一个数组int father[0x3f3f3f];
关于0x3f3f3f,我在末尾说明。

#include<cstdio>
#include<iostream>
#include<vector>//这里我不是用c中的数组的,而是用了向量
using namespace std;
vector <int> father;


int find_gen(int x)//找爸爸,在这里可以多添加一个路径压缩的代码,以防极端情况
{
	int a = x;//记住你正在查询的那个节点
	if (father[x] == x)
	{
		return x;
	}
	while (x != father[x])
	{
		x = father[x];
	}
	while (father[a] != a)//把a的上面的节点全都连接到根节点上面,以后查找就很快
	{
		int temp = father[a];
		father[a] = x;
		a = temp;
	}

	return x;
}
int unite(int x,int y)//合并集合
{
	x=find_gen(x);
	y=find_gen(y);
	if(x!=y)
	father[y] = x;
	return 0;
}
int main(void)
{
	int m, n,k;
	int cnt = 0;
	scanf_s("%d%d", &m, &n);
	scanf_s("%d", &k);
	int x, y;
	int len = m * n;
	for (int i = 0; i <=len; i++)
	{
		father.push_back(i);
	}
	for (int i = 0; i < k; i++)
	{
		cin >> x >> y;
		unite(x, y);
	}
	for (int i = 1; i <= len; i++)
	{
		if (father[i] == i)
		{
			cnt++;
		}
	}
	cout << cnt ;
	return 0;
}

很多程序员都用0x7fffffff来作为无穷大的值,但是由于这个值过大,会出现无穷大加上一个有穷数,出现溢出的情况,由无穷大变成了一个负数。
而0x3f3f3f就是一个比较完美的无穷大的值的选择。

  • 0x3f3f3f的十进制是1061109567,是10^9级别的,和0x7fffffff是一个数量级,而我们在写题是遇到的数据范围,一般都不会超过这个级别,因此可以作为无穷大。
  • 另一方面,因为这个数并不算特别大,所以不会出现无穷大加上一个数据,出现溢出情形。甚至,0x3f3f3f3f+0x3f3f3f3f=2122219134,满足了无穷大加上无穷大还是无穷大的结果,与常识相符。
  • 如果我们想要将某个数组清零,我们通常会使用memset(a,0,sizeof(a))这样的代码来实现,但是当我们想将某个数组全部赋值为其他值,例如无穷大时,就不能使用memset函数而得自己写循环了我们知道这是因为memset是按字节操作的,它能够对数组清零是因为0的每个字节都是0,现在好了,如果我们将无穷大设为0x3f3f3f3f,那么奇迹就发生了,0x3f3f3f3f的每个字节都是0x3f!所以要把一段内存全部置为无穷大,我们只需要memset(a,0x3f,sizeof(a))。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值