BZOJ2429[HAOI2006]聪明的猴子(最小生成树)

题目描述:给出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

题目分析:将树两两建边,权值为两点间的距离,然后用最小生成树kruskal算法求出最短路径中的最长边,再判断每只猴子能不能跳过这个最长边的距离。

#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int q[510],x[1100],y[1100];
int fa[1100000];
struct node
{
    int x,y;double d;
}a[1100000];int len;
int cmp(const void *xx,const void *yy)
{
    node n1=*(node *)xx;
    node n2=*(node *)yy;
    if(n1.d>n2.d) return 1;
    if(n1.dreturn -1;
    return 0;
}
int findfa(int x)
{
    if(fa[x]==x) return x;
    else
    {
        fa[x]=findfa(fa[x]);
        return fa[x];
    }
}
int main()
{
    int n,m;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&q[i]);
    len=0;
    scanf("%d",&m);
    for(int i=1;i<=m;i++) scanf("%d%d",&x[i],&y[i]);
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(i!=j) {len++;a[len].x=i;a[len].y=j;a[len].d=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));}
        }
    }
    qsort(a+1,len,sizeof(node),cmp);
    for(int i=1;i<=m;i++) fa[i]=i;
    int t=0;double maxx=0;
    for(int i=1;i<=len;i++)
    {
        int fx,fy;
        fx=findfa(a[i].x);
        fy=findfa(a[i].y);
        if(fa[fx]!=fa[fy])
        {
            maxx=max(maxx,a[i].d);
            fa[fy]=fx;
            t++; if(t==m-1) break;
        }
    }
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        if(q[i]>=maxx) sum++;
    }
    printf("%d\n",sum);
    return 0;
}

注意一下数据的大小,不要把数组开小。

你可能感兴趣的:(大视野,最小生成树,萌新OI成长经历)