module main; // https://blog.hamayanhamayan.com/entry/2016/07/10/171825 より import std; /* UnionFind:素集合系管理の構造体(union by size) isSame(x, y): x と y が同じ集合にいるか。 計算量はならし O(α(n)) unite(x, y): x と y を同じ集合にする。計算量はならし O(α(n)) treeSize(x): x を含む集合の要素数。 */ struct UnionFind { int[] size, parents; this(int n) // make n trees. { size.length = parents.length = n; foreach (i; 0 .. n) makeTree(i); } void makeTree(int x) { parents[x] = x; // the parent of x is x size[x] = 1; } bool isSame(int x, int y) { return findRoot(x) == findRoot(y); } bool unite(int x, int y) { x = findRoot(x); y = findRoot(y); if (x == y) return false; if (size[x] > size[y]) { parents[y] = x; size[x] += size[y]; } else { parents[x] = y; size[y] += size[x]; } return true; } int findRoot(int x) { if (x != parents[x]) parents[x] = findRoot(parents[x]); return parents[x]; } int treeSize(int x) { return size[findRoot(x)]; } } void main() { // 入力 int N = readln.chomp.to!int; auto X = new int[](N), Y = new int[](N); foreach (ref x, ref y; lockstep(X, Y)) readln.chomp.formattedRead("%d %d", x, y); // 答えの計算と出力 if (N == 0) { writeln(1); return; } auto uf = UnionFind(N); foreach (i; 0 .. N) { foreach (j; i + 1 .. N) { if ((X[j] - X[i]) ^^ 2 + (Y[j] - Y[i]) ^^ 2 <= 100) uf.unite(i, j); } } double ans = 2; foreach (i; 0 .. N) { foreach (j; i + 1 .. N) { if (!uf.isSame(i, j)) continue; double d = ((X[j] - X[i]) ^^ 2 + (Y[j] - Y[i]) ^^ 2).to!double.sqrt; ans = max(ans, d + 2); } } writefln("%.12f", ans); }