【BZOJ2429】聰明的猴子
阿新 • • 發佈:2018-11-04
題目連結: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 namespaceAC程式碼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 intpw2(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 }