import java.util.LinkedList; import java.util.ArrayDeque; import java.util.Queue; import java.util.Scanner; import java.util.Arrays; import java.util.HashSet; public class harry3 { static boolean[][] adj; // I opt for the "less-than-optimal" O(N^3) (instead of O(VE)). static int[] prev; static int R, B; static int[] match; public static void main(String[] args) { int[] xpos, ypos; int target; // Input reading. Scanner sc = new Scanner(System.in); target = sc.nextInt(); B = sc.nextInt(); R = sc.nextInt(); // I swapped R and B. Sorry. xpos = new int[R + B]; ypos = new int[R + B]; for(int i = 0; i < B; i++) { xpos[i + R] = sc.nextInt(); ypos[i + R] = sc.nextInt(); assert(xpos[i + R] <= 10000 && xpos[i + R] >= -10000 && ypos[i + R] <= 10000 && ypos[i + R] >= -10000); } for(int i = 0; i < R; i++) { xpos[i] = sc.nextInt(); ypos[i] = sc.nextInt(); assert(xpos[i] <= 10000 && xpos[i] >= -10000 && ypos[i] <= 10000 && ypos[i] >= -10000); } match = new int[R + B]; long[] dists = new long[R * B]; for (int i = 0; i < R; ++i) for (int j = 0; j < B; ++j) dists[i + R * j] = (xpos[i] - xpos[R+j]) * (xpos[i] - xpos[R+j]) + (ypos[i] - ypos[R+j]) * (ypos[i] - ypos[R+j]); Arrays.sort(dists); int lo = 0, hi = R * B; adj = new boolean[R][B]; while(lo < hi) { // Reset whatever is necessary. int mid = (lo + hi) / 2; for(int i = 0; i < R + B; i++) match[i] = -1; // Build the graph. for(int i = 0; i < R; i++) for(int j = R; j < R + B; j++) { int xdist = xpos[i] - xpos[j], ydist = ypos[i] - ypos[j]; if(xdist * xdist + ydist * ydist <= dists[mid]) adj[i][j - R] = true; else adj[i][j - R] = false; } // Find the matching. int flow = 0; int last; while((last = augmentingPath()) != -1) { flow++; // Update the graph, backtracking though the plants. int cur = last; while(cur != -1) { if(cur >= R) // Blue plant, here we change the matching. { if(match[cur] == -1) assert(cur == last); match[cur] = prev[cur]; match[prev[cur]] = cur; } cur = prev[cur]; } // Ensure that the matching is actually a pairing. for(int i = 0; i < R; i++) if(match[i] != -1) assert(match[match[i]] == i); } int matched = 0; for(int i = 0; i < R; i++) matched += (match[i] != -1) ? 1 : 0; assert(matched == flow); matched = 0; for(int i = R; i < R + B; i++) matched += (match[i] != -1) ? 1 : 0; assert(matched == flow); int hideable_eggs = R + B - flow; if(hideable_eggs >= target) // We can hide enough eggs, so we should increase the minimal distance. lo = mid + 1; else hi = mid; } long sq = (lo == R * B ? dists[lo - 1] : dists[lo]); System.out.println(Math.sqrt(sq)); } static int augmentingPath() { boolean[] visited = new boolean[R + B]; prev = new int[R + B]; for (int i = 0; i < R + B; i++) prev[i] = -1; Queue queue = new ArrayDeque(); for(int i = 0; i < R; i++) if(match[i] == -1) { queue.add(i); visited[i] = true; } while (!queue.isEmpty()) { int cur = queue.remove(); if(cur < R) { for(int i = R; i < R + B; i++) { if(adj[cur][i - R] && !visited[i]) { prev[i] = cur; visited[i] = true; if(match[i] == -1) return i; queue.add(i); } } } else { assert(cur >= R && cur < R + B); assert(match[cur] != -1); int m = match[cur]; prev[m] = cur; visited[m] = true; queue.add(m); } } return -1; } }