COGS 1310. [HAOI2006]聪明的猴子
在一个热带雨林中生存着一群猴子,它们以树上的果子为生。昨天下了一场大雨,现在雨过天晴,但整个雨林的地表还是被大水淹没着,
猴子不会游泳,但跳跃能力比较强,它们仍然可以在露出水面的部分植物的树冠上来回穿梭,以找到喜欢吃的果实。
现在,在这个地区露出水面的有N棵树,假设每棵树本身的直径都很小,可以忽略不计。我们在这块区域上建立直角坐标系,则每一棵树的位置由其所对应的坐标表示(任意两棵树的坐标都不相同)。
在这个地区住着的猴子有M个,下雨时,它们都躲到了茂密高大的树冠中,没有被大水冲走。由于各个猴子的年龄不同、身体素质不同,它们跳跃的能力不同。有的猴子跳跃的距离比较远(当然也可以跳到较近的树上),而有些猴子跳跃的距离就比较近。这些猴子非常聪明,它们通过目测就可以准确地判断出自己能否跳到对面的树上。
任务:现已知猴子的数量及每一个猴子的最大跳跃的距离,还知道露出水面的每一棵树的坐标,你的任务是统计有多少猴子可以在这个地区露出水面的所有树冠上觅食。
【输入格式】
第一行一个整数,表示猴子的个数 M(2<=M<=500)
第二行为M个整数,依次表示猴子的最大跳跃距离(每个整数值在1---1000之间)
第三行为一个整数,表示树的总棵树N(2<=N<=1000)
第四行至第N+3行为N棵树的坐标(横纵坐标均为整数,范围为:-1000--1000)
【输出格式】
输出只有一行,包括一个整数,表示可以有这个地区的所有树冠上觅食的猴子数。
【样例输入】
4 1 2 3 4 6 0 0 1 0 1 2 -1 -1 -2 0 2 2
【样例输出】
3
【提示】
对于40%的数据,保证有2<=N<=100,1<=M<=100
对于100%的数据,保证有2<=N<=1000,1<=M<=500
注意建边,可能会出现一些小问题
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define maxn 3000000+15 int n,m,fa[maxn],num,sum,tot; double a[maxn],maxdis; int x[maxn],y[maxn]; struct Edge{ int x,y; double dis; }edge[maxn]; bool cmp(Edge a,Edge b) { return a.dis<b.dis; } int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } void add_edge(int u,int v) { num++; edge[num].x=u; edge[num].y=v; edge[num].dis=double(sqrt((x[u]-x[v])*(x[u]-x[v])+(y[u]-y[v])*(y[u]-y[v]))); } int main() { freopen("monkey.in","r",stdin); freopen("monkey.out","w",stdout); scanf("%d",&m); for(int i=1;i<=m;i++) scanf("%lf",a+i); scanf("%d",&n); for(int i=1;i<=n;i++) fa[i]=i,scanf("%d%d",x+i,y+i); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j) add_edge(i,j); sort(edge+1,edge+num+1,cmp); for(int i=1;i<=num;i++) { int fx=find(edge[i].x),fy=find(edge[i].y); if(fx==fy) continue; num++; fa[fx]=fy; maxdis=edge[i].dis; if(num==n-1) break; } for(int i=1;i<=m;i++) if(a[i]>=maxdis) sum++; printf("%d\n",sum); return 0; }