Description
在一个热带雨林中生存着一群猴子,它们以树上的果子为生。昨天下了一场大雨,现在雨过天晴,但整个雨林的地
表还是被大水淹没着,部分植物的树冠露在水面上。猴子不会游泳,但跳跃能力比较强,它们仍然可以在露出水面
的不同树冠上来回穿梭,以找到喜欢吃的果实。现在,在这个地区露出水面的有N棵树,假设每棵树本身的直径都
很小,可以忽略不计。我们在这块区域上建立直角坐标系,则每一棵树的位置由其所对应的坐标表示(任意两棵树
的坐标都不相同)。在这个地区住着的猴子有M个,下雨时,它们都躲到了茂密高大的树冠中,没有被大水冲走。由
于各个猴子的年龄不同、身体素质不同,它们跳跃的能力不同。有的猴子跳跃的距离比较远(当然也可以跳到较近
的树上),而有些猴子跳跃的距离就比较近。这些猴子非常聪明,它们通过目测就可以准确地判断出自己能否跳到
对面的树上。【问题】 现已知猴子的数量及每一个猴子的最大跳跃距离,还知道露出水面的每一棵树的坐标,你
的任务是统计有多少个猴子可以在这个地区露出水面的所有树冠上觅食。
猴子的个数M(2<=M<=500);
树的总棵数N(2<=N<=1000);
Solution
题意比较麻烦。m个点最小生成树,如果一只猴子能跳过最长的边,那么这只猴子一定能跳完所有树
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))
const int N=525005;
const int E=550005;
struct edge{int x,y,w;}e[E];
int fa[N],d[N],x[N],y[N],edCnt=0,ans=0,w;
int get_father(int now) {return (!fa[now])?(now):(fa[now]=get_father(fa[now]));}
int cmp(edge a,edge b) {return a.w<b.w;}
int merge(int x,int y) {x=get_father(x); y=get_father(y); return (x==y)?(0):((fa[x]=y)!=0);}
int main(void) {
int n; scanf("%d",&n);
rep(i,1,n) scanf("%d",&d[i]);
int m; scanf("%d",&m);
rep(i,1,m) scanf("%d%d",&x[i],&y[i]);
rep(i,1,m) rep(j,i+1,m) e[++edCnt]=(edge){i,j,(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])};
std:: sort(e+1,e+edCnt+1,cmp);
rep(i,1,edCnt) if (merge(e[i].x,e[i].y)) w=e[i].w;
rep(i,1,n) if (d[i]*d[i]>=w) ans++;
printf("%d\n", ans);
return 0;
}