[bzoj2429][HAOI2006]聪明的猴子 kruskal

本文介绍了一个经典的算法问题——HAOI2006 聪明的猴子问题,该问题涉及猴子在热带雨林中通过跳跃在不同树冠上寻找食物的情景。文章详细描述了输入输出格式、样例输入输出以及问题背景,并提供了一段C++代码作为解决方案。

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

2429: [HAOI2006]聪明的猴子

Time Limit: 10 Sec  Memory Limit: 128 MB
[ Submit][ Status][ Discuss]

Description

在一个热带雨林中生存着一群猴子,它们以树上的果子为生。昨天下了一场大雨,现在雨过天晴,但整个雨林的地
表还是被大水淹没着,部分植物的树冠露在水面上。猴子不会游泳,但跳跃能力比较强,它们仍然可以在露出水面
的不同树冠上来回穿梭,以找到喜欢吃的果实。现在,在这个地区露出水面的有N棵树,假设每棵树本身的直径都
很小,可以忽略不计。我们在这块区域上建立直角坐标系,则每一棵树的位置由其所对应的坐标表示(任意两棵树
的坐标都不相同)。在这个地区住着的猴子有M个,下雨时,它们都躲到了茂密高大的树冠中,没有被大水冲走。由
于各个猴子的年龄不同、身体素质不同,它们跳跃的能力不同。有的猴子跳跃的距离比较远(当然也可以跳到较近
的树上),而有些猴子跳跃的距离就比较近。这些猴子非常聪明,它们通过目测就可以准确地判断出自己能否跳到
对面的树上。【问题】 现已知猴子的数量及每一个猴子的最大跳跃距离,还知道露出水面的每一棵树的坐标,你
的任务是统计有多少个猴子可以在这个地区露出水面的所有树冠上觅食。

Input

第1行为一个整数,表示猴子的个数M(2<=M<=500);
第2行为M个整数,依次表示猴子的最大跳跃距离(每个整数值在1--1000之间);
第3行为一个整数表示树的总棵数N(2<=N<=1000);
第4行至第N+3行为N棵树的坐标(横纵坐标均为整数,范围为:-1000--1000)。
(同一行的整数间用空格分开)

Output

包括一个整数,表示可以在这个地区的所有树冠上觅食的猴子数

Sample Input

4
1 2 3 4
6
0 0
1 0
1 2
-1 -1
-2 0
2 2

Sample Output

3

HINT

2<=N <= 1000,1<=M=500 

Source

我是智障
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N = 1005;
struct Edge{
	int u,v,w;
}e[N*N];
int a[N],x[N],y[N],fa[N],n,m,maxn,ans,scnt,cnt;
void insert( int u, int v, int w ){
	e[++cnt].u = u; e[cnt].v = v; e[cnt].w = w;
}
int find( int x ){ return fa[x] == x ? x : fa[x] = find(fa[x]); }
bool cmp( Edge a, Edge b ){ return a.w < b.w; }
void kruskal(){
	std::sort( e+1, e+cnt+1, cmp );
	for( int i = 1; i <= cnt; i++ ){
		int A = find(e[i].u), B = find(e[i].v);
		if( A != B ){
			fa[A] = fa[B]; scnt++;
			if( scnt == m-1 ) { maxn = e[i].w; return ; }
		}
	}
}
int main(){
	scanf("%d", &n); for( int i = 1; i <= n; i++ ) scanf("%d", &a[i]);
	scanf("%d", &m); for( int i = 1; i <= m; i++ ) scanf("%d%d", &x[i], &y[i]),fa[i] = i;
	for( int i = 1; i <= m; i++ )
		for( int j = i+1; j <= m; j++ )
			insert( i, j,(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]) );
	kruskal();
	for( int i = 1; i <= n; i++ ) if( a[i]*a[i] >= maxn ) ans++;
	printf("%d", ans);
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值