题解 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 }