1. 程式人生 > >題解 P2504 【[HAOI2006]聰明的猴子】

題解 P2504 【[HAOI2006]聰明的猴子】

這道題要坑死人啊。。。

第一次做40分,其他RE,改了一次之後就變成20分了。。。

究其原因,是有一個數組(dis)開的太小了,於是最後本蒟蒻就隨手開了個五百萬,然後,就AC了

看到有一篇題解說求距離最好不開根,經本蒟蒻實驗,開不開根並不影響結果,全看個人喜好。

本蒟蒻還加了一個快讀,其實也沒有必要,只是第一次RE的時候不小心看成了TLE,為了縮短時間才寫的。

總體來說,這是一道Kruskal的題廢話

需要注意的一個點在於題目所求的與裸題有差異。

其餘的好像問題也不大,只要不像本蒟蒻一樣視力不好就不會錯得太離譜。

總而言之,AC程式碼如下(並查集find函式帶優化):

 1
#include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 inline int qread() { 8 int x = 0, f = 1; 9 char c = getchar(); 10 while(c < '0' || c > '9') { 11 if(c == '-') f = -1; 12 c = getchar();
13 } 14 while(c >= '0' && c <= '9') { 15 x = x * 10 + (c - '0'); 16 c = getchar(); 17 } 18 return x * f; 19 } 20 21 const int maxn = 1010; 22 23 int m, n, ans = 0, cnt = 0; 24 int f[maxn], leap[maxn], x[maxn], y[maxn]; 25 26 struct node { 27 int x, y; 28 int
val; 29 }dis[5000005]; 30 31 bool cmp(node a, node b) { 32 return a.val < b.val; 33 } 34 35 int find(int x) { 36 int r = x; 37 while(r != f[r]) r = f[r]; 38 int i = x, j; 39 while(f[i] != r) { 40 j = f[i]; 41 f[i] = r; 42 i = j; 43 } 44 return r; 45 } 46 47 void merge(int x, int y) { 48 x = find(x); 49 y = find(y); 50 if(x != y) f[y] = x; 51 } 52 53 double dt(int x1,int x2,int y1,int y2) { 54 return sqrt(pow(double(x1 - x2), 2) + pow(double(y1 - y2), 2)); 55 } 56 57 int main() { 58 cin >> m; 59 for(int i = 1; i <= m; i++) cin >> leap[i]; 60 cin >> n; 61 for(int i = 1; i <= n; i++) cin >> x[i] >> y[i]; 62 for(int i = 1; i <= maxn - 1; i++) f[i] = i; 63 64 for(int i = 1; i <= n; i++) 65 for(int j = i + 1; j <= n; j++) { 66 dis[++cnt].x = i; 67 dis[cnt].y = j; 68 dis[cnt].val = dt(x[i], x[j], y[i], y[j]); 69 } 70 71 72 sort(dis + 1, dis + cnt + 1, cmp); 73 for(int i = 1; i <= cnt; i++) 74 if(find(dis[i].x) != find(dis[i].y)) { 75 ans = dis[i].val; 76 merge(dis[i].x, dis[i].y); 77 } 78 79 int sum = 0; 80 for(int i = 1; i <= m; i++) if(leap[i] >= ans) sum++; 81 82 cout << sum; 83 }