[BZOJ2429] [HAOI2006]聪明的猴子

题目描述

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

对于40%的数据,保证有2<=N <=100,1<=M<=100

对于全部的数据,保证有2<=N <= 1000,1<=M=500

题目分析:

因为需要互相连通 对于比较弱的猴子来说 应该是在最小生成树上跳的状态更优 那么求出最小生成树上的最大边长 判断有多少猴子满足要求就好了

写这道题的时候各种手残QAQ

#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int c[10000];
int f[10000];
int find(int x)
{
	return (f[x]==x)?x:f[x]=find(f[x]);
}
int tot;
struct your
{
	int x,y,c;
}a[6000000];
struct mapp
{
	int x,y;
}b[6000000];
bool cmp(your j,your k)
{
	return j.c<k.c;
}
int maxx;
void klu()
{
	int cnt=0;
	for(int i=1;i<=tot;i++)
	{
		int dx=find(a[i].x);
		int dy=find(a[i].y);
		if(dx!=dy)
			f[dx]=dy,cnt++;
		if(cnt==m-1)
		{
			maxx=a[i].c;
			return ;
		}
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&c[i]);
	scanf("%d",&m);
	for(int i=1;i<=m;i++) f[i]=i;
	for(int i=1;i<=m;i++)
		scanf("%d%d",&b[i].x,&b[i].y);
	for(int i=1;i<=m;i++)
		for(int j=i+1;j<=m;j++)
		{
			tot++;
			a[tot].x=i;
			a[tot].y=j;
			a[tot].c=(b[i].x-b[j].x)*(b[i].x-b[j].x)+(b[i].y-b[j].y)*(b[i].y-b[j].y);
		}
	sort(a+1,a+tot+1,cmp);
	klu();
	int ans=0;
	for(int i=1;i<=n;i++)
		if(c[i]*c[i]>=maxx) ans++;
	printf("%d",ans);
    return 0;
}

发表评论

邮箱地址不会被公开。 必填项已用*标注