https://www.luogu.com.cn/problem/P2504
# [HAOI2006]聪明的猴子
## 题目描述
在一个热带雨林中生存着一群猴子,它们以树上的果子为生。昨天下了一场大雨,现在雨过天晴,但整个雨林的地表还是被大水淹没着,部分植物的树冠露在水面上。猴子不会游泳,但跳跃能力比较强,它们仍然可以在露出水面的不同树冠上来回穿梭,以找到喜欢吃的果实。
现在,在这个地区露出水面的有N棵树,假设每棵树本身的直径都很小,可以忽略不计。我们在这块区域上建立直角坐标系,则每一棵树的位置由其所对应的坐标表示(任意两棵树的坐标都不相同)。
在这个地区住着的猴子有M个,下雨时,它们都躲到了茂密高大的树冠中,没有被大水冲走。由于各个猴子的年龄不同、身体素质不同,它们跳跃的能力不同。有的猴子跳跃的距离比较远(当然也可以跳到较近的树上),而有些猴子跳跃的距离就比较近。这些猴子非常聪明,它们通过目测就可以准确地判断出自己能否跳到对面的树上。
【问题】现已知猴子的数量及每一个猴子的最大跳跃距离,还知道露出水面的每一棵树的坐标,你的任务是统计有多少个猴子可以在这个地区露出水面的所有树冠上觅食。
## 输入格式
输入文件monkey.in包括:
第1行为一个整数,表示猴子的个数M(2<=M<=500);
第2行为M个整数,依次表示猴子的最大跳跃距离(每个整数值在1--1000之间);
第3行为一个整数表示树的总棵数N(2<=N<=1000);
第4行至第N+3行为N棵树的坐标(横纵坐标均为整数,范围为:-1000--1000)。
(同一行的整数间用空格分开)
## 输出格式
输出文件monkey.out包括一个整数,表示可以在这个地区的所有树冠上觅食的猴子数。
## 样例 #1
### 样例输入 #1
```
4
1 2 3 4
6
0 0
1 0
1 2
-1 -1
-2 0
2 2
```### 样例输出 #1
```
3
```## 提示
【数据规模】
对于40%的数据,保证有2<=N <=100,1<=M<=100
对于全部的数据,保证有2<=N <= 1000,1<=M=500
AC代码:
/*
突然想坐火车了 .
一定要靠在窗边.
这样便可以避开旁人奇怪的.
东张西望的眼神.
一定要带上耳机 .
这样就听不到车厢里琐碎的声音.
我知道火车要开向何方 .
也知道何时到达 .
很重要很幸福的一件事就是 .
在到达之前的那段时间我是自由的.
尽管车厢里没有风.
但看着窗外的我似乎.
触到了外面田野上的清风...
如果可以.
我想化作 山间的风.
吹过草海 吹过花田.
轻轻拂在你耳边说我爱你.
可你却只听见了一阵风声.
摆摆头便离去了.
而我也不介意.
你也不是山谷.
所以不会有回应.
因为比起你.
我更爱这绿草蓝花无知无识.
便不会伤心难过.
那是独属于我们的花田.
浪漫在原野上肆意狂奔.
你摘下我头上的落叶.
然后一起藏进树上看星火夜幕.
多年后再闻见玫瑰森香.
我想我还会想起那处山谷 和那个你....
*/
#include<bits/stdc++.h>
using namespace std;
const int n=1e6;
int A[n];//猴子的最大跳跃距离
int B[n];//节点的父节点
struct yqyqyq{
int x,y;
}C[n];
struct wlwlwl{
int u,v;
int c;
}D[n];
int find(int x)
{
if(B[x]!=x) B[x]=find(B[x]);
return B[x];
}
bool cmp(const wlwlwl&x,const wlwlwl&y)
{
return x.c<y.c;
}
int main()
{
// freopen("monkey.in","r",stdin);
// freopen("monkey.out","w",stdout);
int M;
scanf("%d",&M);
for(int i=1;i<=M;i++){
scanf("%d",&A[i]);
A[i]=A[i]*A[i];
}
int N;
scanf("%d",&N);
for(int i=1;i<=N;i++) B[i]=i;
for(int i=1;i<=N;i++) scanf("%d%d",&C[i].x,&C[i].y);
int d=0;
for(int i=1;i<=N;i++)
{
for(int j=i+1;j<=N;j++)
{
d++;
D[d].u=i;
D[d].v=j;
D[d].c=(C[i].x-C[j].x)*(C[i].x-C[j].x)+(C[i].y-C[j].y)*(C[i].y-C[j].y);
}
}
sort(D+1,D+d+1,cmp);
int sum=0;
int cnt=0;
for(int i=1;i<=d;i++)
{
int a=find(D[i].u);
int b=find(D[i].v);
if(a!=b)
{
B[a]=b;
sum++;
}
if(sum==N-1){
cnt=i;
break;
}
}
int wyy=0;
for(int i=1;i<=M;i++)
{
if(A[i]>=D[cnt].c) wyy++;
}
printf("%d\n",wyy);
return 0;
}