Description

聪聪研究发现, 荒岛野人总是过着群居的生活, 但是, 并不是整个荒岛上的所有野人都属于同一个部落, 野人们总是拉帮结派形成属于自己的部落, 不同的部落之间则经常发生争斗. 只是, 这一切都成为谜团了----聪聪根本就不知道部落究竟是如何分布的.

不过好消息是, 聪聪得到了一份荒岛的地图. 地图上标注了 \(n\) 个野人居住的地点 (可以看作是平面上的坐标). 我们知道, 同一个部落的野人总是生活在附近. 我们把两个部落的距离, 定义为部落中距离最近的那两个居住点的距离. 聪聪还获得了一个有意义的信息----这些野人总共被分为了 \(k\) 个部落! 这真是个好消息. 聪聪希望从这些信息里挖掘出所有部落的详细信息. 他正在尝试这样一种算法:

对于任意一种部落划分的方法, 都能够求出两个部落之间的距离, 聪聪希望求出一种部落划分的方法, 使靠得最近的两个部落尽可能远离. 例如, 下面的左图表示了一个好的划分, 而右图则不是. 请你编程帮助聪聪解决这个难题.

Input

第一行包含两个整数 \(n\)\(k\), 分别代表了野人居住点的数量和部落的数量.

接下来 \(n\) 行, 每行包含两个正整数 \(x, y\), 描述了一个居住点的坐标 \((0 \leq x, y \leq 10000)\).

Output

输出一行, 为最优划分时, 最近的两个部落的距离, 精确到小数点后两位.

Sample Input

4 2
0 0
0 1
1 1
1 0

Sample Output

1.00

Data Range

对于所有数据, 满足:\(1 \leq k \leq n \leq 1000\).

Explanation

对于任何一个距离, 不会有一个部落里的两个人距离大于该距离. 这个距离越大, 我们观测到的部落数量就会越少 (不单调), 反之亦然.

所以我们可以考虑二分这个距离, 然后判断哪些人可以构成部落, 用并查集维护即可. 时间复杂度 \(O(n^2 \alpha(n))\).

Source Code


#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cmath>

using namespace std;
typedef long long lli;
typedef double llf;
const int maxn = 1010;
const llf epsilon = 1e-5;

template <typename _T>
_T sqr(_T a) { return a * a; }

class DisjointSet
{
public:
    int par[maxn];
    int n;
    int find(int p)
    {
        if (par[p] == p)
            return p;
        return par[p] = find(par[p]);
    }
    void join(int p, int q)
    {
        p = find(p);
        q = find(q);
        if (p == q)
            return ;
        par[p] = q;
        n -= 1;
        return ;
    }
    void init(int n)
    {
        this->n = n;
        for (int i = 1; i <= n; i++)
            par[i] = i;
        return ;
    }
} djs;

int n, K, x[maxn], y[maxn];
llf dist[maxn][maxn];

bool judge(llf dis)
{
    djs.init(n);
    for (int i = 1; i <= n; i++)
        for (int j = i + 1; j <= n; j++)
            if (dist[i][j] <= dis)
                djs.join(i, j);
    if (djs.n >= K)
        return true;
    return false;
}

int main(int argc, char** argv)
{
    scanf("%d%d", &n, &K);
    for (int i = 1; i <= n; i++)
        scanf("%d%d", &x[i], &y[i]);
    // Calculating distance
    for (int i = 1; i <= n; i++)
        for (int j = i; j <= n; j++)
            dist[i][j] = dist[j][i] = sqrt(sqr(x[i] - x[j]) + sqr(y[i] - y[j]));
    // Binary searching, and judging
    llf l = 0, r = 1.0e9;
    while (r - l > epsilon) {
        llf mid = (l + r) / 2;
        if (judge(mid))
            l = mid;
        else
            r = mid;
    }
    // Output
    printf("%.2lf\n", l);
    return 0;
}