http://soj.sysu.edu.cn/show_problem.php?pid=1000&cid=1750
题目说是单链聚类,其实就是最小生成树,输出第k-1大的边;
我用的是kruskal算法:
1 #include <iostream>
2 #include <cstdio>
3 #include <cstring>
4 #include <cmath>
5 #include <algorithm>
6 #include <cstdlib>
7
8 using namespace std;
9
10 const double eps = 1e-6;
11 int a[10005];
12 double res[10005]; //一开始数组太小RE,因为最多有100*100条边,于是一气之下把数组全部改为一万
13 int cnt;
14
15 struct point {
16 int x;
17 int y;
18 int id;
19 }p[10005];
20
21 struct Node {
22 int u;
23 int v;
24 double l;
25 }node[10005];
26
27 void init()
28 {
29 for(int i=1; i<=10005; i++)
30 a[i] = i;
31 }
32
33 int find_set(int x)
34 {
35 return (x == a[x]) ? x : (a[x] = find_set(a[x]));
36 }
37
38 void union_set(int x, int y)
39 {
40 a[x] = y;
41 }
42
43 void kruskal(int n)
44 {
45 init();
46 for(int j=0; j<n; j++)
47 {
48 int x = find_set(node[j].u);
49 int y = find_set(node[j].v);
50 if(x != y)
51 {
52 union_set(x, y);
53 res[cnt++] = node[j].l;
54 }
55 }
56 }
57
58 bool cmp(Node a, Node b)
59 {
60 return b.l > (a.l+eps); //注意浮点数的比较
61 }
62
63 int main()
64 {
65 int n, k;
66 while(scanf("%d%d", &n, &k) != EOF)
67 {
68 cnt=0;
69 int id=1;
70 for(int i=0; i<n; i++)
71 {
72 scanf("%d%d", &p[i].x, &p[i].y);
73 p[i].id = id++; //把每个坐标换成一个编号:1,2,3....
74 }
75
76 int count=0;
77 for(int i=0; i<n; i++)
78 {
79 for(int j=i+1; j<n; j++)
80 {
81 node[count].u = p[i].id;
82 node[count].v = p[j].id;
83 node[count++].l = sqrt((p[i].x-p[j].x)*(p[i].x-p[j].x) + (p[i].y-p[j].y)*(p[i].y-p[j].y));
84 }
85 }
86 sort(node, node+count, cmp);
87 kruskal(count);
88 printf("%.2lf\n", res[cnt-k+1]);
89 }
90
91 return 0;
92 }