#include <bits/stdc++.h>
using namespace std;
// Hopcroft-Karp algorithm: Fast bipartite matching
// Returns maximum matching between left side (nl nodes) and right side (nr nodes)
int maxMatch(vector<vector<int>>& g, int nl, int nr) {
const int INF = 1e9;
vector<int> ml(nl, -1), mr(nr, -1), lv(nl);
// ml[u] = which right node is u matched to (-1 if unmatched)
// mr[v] = which left node is v matched to (-1 if unmatched)
// lv[u] = level of left node u in BFS layering
// Build level graph using BFS from unmatched left nodes
auto bfs = [&]() {
queue<int> q;
for (int u = 0; u < nl; u++) {
if (ml[u] == -1) {
lv[u] = 0; // Start from unmatched nodes
q.push(u);
} else {
lv[u] = INF;
}
}
bool ok = false; // Did we reach any unmatched right node?
while (!q.empty()) {
int u = q.front();
q.pop();
for (int v : g[u]) {
int p = mr[v]; // Who is v matched to?
if (p != -1 && lv[p] == INF) {
lv[p] = lv[u] + 1; // Set level
q.push(p);
}
if (p == -1) ok = true; // Found unmatched right node
}
}
return ok;
};
// DFS to find augmenting paths in level graph
function<bool(int)> dfs = [&](int u) {
for (int v : g[u]) {
int p = mr[v];
// Either v is unmatched, or follow alternating path
if (p == -1 || (lv[p] == lv[u] + 1 && dfs(p))) {
ml[u] = v;
mr[v] = u;
return true; // Found augmenting path
}
}
lv[u] = INF; // Mark as processed
return false;
};
int res = 0;
// Repeat: build levels, then find all augmenting paths
while (bfs()) {
for (int u = 0; u < nl; u++) {
if (ml[u] == -1 && dfs(u)) {
res++;
}
}
}
return res;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
// Problem: n cats and n mice at different positions
// Select K animals total (some cats + some mice)
// Minimize the maximum distance between any selected cat and selected mouse
vector<pair<int, int>> cat(n), mouse(n);
for (int i = 0; i < n; i++) {
cin >> cat[i].first >> cat[i].second;
}
for (int i = 0; i < n; i++) {
cin >> mouse[i].first >> mouse[i].second;
}
// Precompute squared distances (avoid sqrt)
vector<vector<long long>> d2(n, vector<long long>(n));
vector<long long> vals;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
long long dx = cat[i].first - mouse[j].first;
long long dy = cat[i].second - mouse[j].second;
long long dist = dx * dx + dy * dy;
d2[i][j] = dist;
vals.push_back(dist);
}
}
// Get unique sorted distances for binary search
sort(vals.begin(), vals.end());
vals.erase(unique(vals.begin(), vals.end()), vals.end());
// Key idea: For maximum distance threshold D:
// Build bipartite graph of "BAD" edges where dist(cat, mouse) > D
// Need to select K animals with NO bad edges between selected cats/mice
// = independent set of size K in bipartite graph
// In bipartite: maxIndependentSet = 2n - maxMatching
// Feasible if: 2n - maxMatching >= K, i.e., maxMatching <= 2n - K
auto check = [&](long long D) -> bool {
// Build bipartite graph: edge if distance > D (BAD edge)
vector<vector<int>> g(n);
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (d2[i][j] > D) { // BAD edge (too far apart)
g[i].push_back(j);
}
}
}
// Find max matching in BAD edges graph
int m = maxMatch(g, n, n);
// Can we select K animals avoiding all bad edges?
// Max independent set = 2n - m
return (2 * n - m) >= k;
};
// Binary search for minimum possible maximum distance
int l = 0, r = vals.size() - 1;
while (l < r) {
int mid = (l + r) / 2;
if (check(vals[mid])) {
r = mid; // Can achieve this threshold, try smaller
} else {
l = mid + 1; // Need bigger threshold
}
}
// Convert squared distance back to actual distance
double ans = sqrt((double)vals[l]);
cout << fixed << setprecision(12) << ans << "\n";
return 0;
}