【BZOJ2429】聪明的猴子

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2429


比较简单的一道题目。。。

从一棵树出发蹦到其他所有树,实际上,把n-1条边就可以将这n个点连通,而最小生成树的最大权值又是所有生成树中最小的,因此我们需要构造一棵最小生成树,然后将m个猴子的跳跃距离和MST的最大边权比较,统计答案即可。

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <algorithm>
 4 
 5 using namespace std;
 6 
 7 const int maxm = 505, maxn = 1e3 + 5;
 8 
 9 int monkey[maxm], treex[maxn], treey[maxn];
10 
11 struct Edge {
12     int u, v;
13     double w;
14     bool operator < (const Edge& rhs) const {
15         return w < rhs.w;
16     }
17 } edge[maxn * maxn / 2];
18 
19 inline int pw2(int x) {
20     return x * x;
21 }
22 
23 inline double dis(int i, int j) {
24     return sqrt(pw2(treex[i] - treex[j]) + pw2(treey[i] - treey[j]));
25 }
26 
27 int m, n, eid, fa[maxn];
28 
29 int dj_find(int i) {
30     if (i == fa[i]) return i;
31     else return fa[i] = dj_find(fa[i]);
32 }
33 
34 inline void dj_merge(int a, int b) {
35     fa[dj_find(a)] = dj_find(b);
36 }
37 
38 inline double kruskal() {
39     for (int i = 1; i <= n; ++i) fa[i] = i;
40     sort(edge + 1, edge + eid + 1);
41     int cnt = 0;
42     for (int i = 1; i <= eid; ++i) {
43         int u = edge[i].u, v = edge[i].v, w = edge[i].w;
44         if (dj_find(u) != dj_find(v)) {
45             dj_merge(u, v);
46             if (++cnt == n - 1) return w;
47         }
48     }
49     return edge[eid].w;
50 }
51 
52 int main() {
53     scanf("%d", &m);
54     for (int i = 1; i <= m; ++i) scanf("%d", &monkey[i]);
55     scanf("%d", &n);
56     for (int i = 1; i <= n; ++i) scanf("%d%d", &treex[i], &treey[i]);
57     for (int i = 1; i < n; ++i)
58         for (int j = i + 1; j <= n; ++j) {
59             edge[++eid].u = i;
60             edge[eid].v = j;
61             edge[eid].w = dis(i, j);
62         }
63     int ans = 0;
64     double me = kruskal();
65     for (int i = 1; i <= m; ++i)
66         if (monkey[i] >= me) ++ans;
67     printf("%d", ans);
68     return 0;
69 }
AC代码

猜你喜欢

转载自www.cnblogs.com/Mr94Kevin/p/9903053.html