解法:一开始没想到怎么写,但是慢慢觉得,同一个部落里面的距离都是尽量短的,然后就像题目中的图一样两个部落之间的距离就会很长,这个长度其实是由这个部落里面某个人连出去和另一个部落的某个人的距离。我们直接跑一遍最小生成树就好了,这样自己部落的人的距离就是尽量短,然后这个生成树最长的几条边里面,直接输出倒数第k-1条即可。
代码如下:
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<utility>
#include<stack>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<ctime>
#include<set>
using namespace std;
typedef pair<int, int> pii;
const int maxn = 1e5 + 5;
const int maxm = 1e6 + 5;
int n, k, ppp;
pii p[maxn];
vector<double>len;
struct Node {
int u, v;
double c;
bool operator < (const Node& tmp) const {
if(c < tmp.c)
return 1;
return 0;
}
}edge[maxm];
int par[maxn];
int Find(int x) {
int root, tmp = x;
while(x != par[x])
x = par[x];
root = x;
x = tmp;
while(x != par[x]) {
tmp = par[x];
par[x] = root;
x = tmp;
}
return root;
}
void Union(int x, int y) {
par[y] = x;
}
void kruskal() {
for(int i = 0; i < ppp; i++) {
int x = Find(edge[i].u);
int y = Find(edge[i].v);
if(x != y) {
Union(x, y);
len.push_back(edge[i].c);
}
}
}
double Count(int i, int j) {
int x1 = p[i].first, x2 = p[j].first;
int y1 = p[i].second, y2 = p[j].second;
return sqrt(1.0 * (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
int main() {
#ifndef ONLINE_JUDGE
freopen("D:\\in.txt", "r", stdin);
#endif // ONLINE_JUDGE
scanf("%d%d", &n, &k);
for(int i = 1, x, y; i <= n; i++) {
scanf("%d%d", &x, &y);
p[i].first = x;
p[i].second = y;
}
for(int i = 1; i <= n; i++) {
for(int j = i + 1; j <= n; j++) {
double d = Count(i, j);
edge[ppp].u = i;
edge[ppp].v = j;
edge[ppp].c = d;
ppp++;
}
}
sort(edge, edge + ppp);
for(int j = 1; j < maxn; j++)
par[j] = j;
kruskal();
printf("%.2f\n", len[len.size() - k + 1]);
return 0;
}