Java教程

1037 [HAOI2006]聪明的猴子 看有多少能到达所有点 最小生成树

本文主要是介绍1037 [HAOI2006]聪明的猴子 看有多少能到达所有点 最小生成树,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 链接:https://ac.nowcoder.com/acm/contest/26077/1037
来源:牛客网

题目描述

在一个热带雨林中生存着一群猴子,它们以树上的果子为生。昨天下了一场大雨,现在雨过天晴,但整个雨林的地 表还是被大水淹没着,部分植物的树冠露在水面上。猴子不会游泳,但跳跃能力比较强,它们仍然可以在露出水面 的不同树冠上来回穿梭,以找到喜欢吃的果实。现在,在这个地区露出水面的有N棵树,假设每棵树本身的直径都 很小,可以忽略不计。我们在这块区域上建立直角坐标系,则每一棵树的位置由其所对应的坐标表示(任意两棵树 的坐标都不相同)。在这个地区住着的猴子有M个,下雨时,它们都躲到了茂密高大的树冠中,没有被大水冲走。由 于各个猴子的年龄不同、身体素质不同,它们跳跃的能力不同。有的猴子跳跃的距离比较远(当然也可以跳到较近 的树上),而有些猴子跳跃的距离就比较近。这些猴子非常聪明,它们通过目测就可以准确地判断出自己能否跳到 对面的树上。 【问题】 现已知猴子的数量及每一个猴子的最大跳跃距离,还知道露出水面的每一棵树的坐标,你 的任务是统计有多少个猴子可以在这个地区露出水面的所有树冠上觅食。

输入描述:

第1行为一个整数,表示猴子的个数M(2 ≤ M ≤ 500);
第2行为M个整数,依次表示猴子的最大跳跃距离(每个整数值在1--1000之间);
第3行为一个整数表示树的总棵数N(2 ≤ N ≤ 1000);
第4行至第N+3行为N棵树的坐标(横纵坐标均为整数,范围为:-1000--1000)。(同一行的整数间用空格分开)

输出描述:

包括一个整数,表示可以在这个地区的所有树冠上觅食的猴子数
示例1

输入

复制
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≤1002 \le N  \le 100,1 \le M \le 1002≤N≤100,1≤M≤100

对于全部的数据,保证有2≤N≤1000,1≤M=5002 \le N  \le  1000,1 \le M=5002≤N≤1000,1≤M=500

分析

题意:每只猴子有不同的跳跃距离,问总共有多少只猴子可以跳到所有点。

就是问多少只猴子可以生成最小生成树

点数1000,说明边数1000000 / 2 = 500000。总共有500只猴子。

500 * 500000 = 2e7...

sort排序复杂度:mlogm = 1e6

//-------------------------代码----------------------------

//#define int ll
const int N = 1e5+10;
int n,m;
int h[N];

struct node {
    int x,y,c;
    bool operator<(const node& x) const {
        return c < x.c;
    }
} p[N];

V<node> q;

int dis(int x,int y) {
    return (p[x].x - p[y].x) * (p[x].x - p[y].x) + (p[x].y - p[y].y) * (p[x].y - p[y].y);
}
int f[N];
int find(int x){return x == f[x]? x:f[x] = find(f[x]);}

void solve()
{
//    cin>>n>>m;
    cin>>m;
    fo(i,1,m)cin>>h[i];
    
    cin>>n;
    fo(i,1,n) {
        int x,y;cin>>x>>y;
        p[i] = {x,y};
    }
    fo(i,1,n) {
        fo(j,i+1,n) {
            q.pb({i,j,(int)sqrt(dis(i,j))});
        }
    }
    sort(all(q));
    int ans = 0;
    fo(i,1,m) {
        int cnt = n - 1;
        fo(i,1,n) f[i] = i;
        for(auto it:q) {
            if(it.c > h[i] || cnt == 0) break;
            int a = it.first,b = it.second;
            if(find(a) != find(b)) {
                f[find(a)] = find(b);
                cnt -- ;
            }
        }
//         db(cnt)
        if(!cnt) ans ++ ;
    }
    cout<<ans<<endl;
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

这篇关于1037 [HAOI2006]聪明的猴子 看有多少能到达所有点 最小生成树的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!