#include <bits/stdc++.h>
using namespace std;
#define repr(i,a,b) for(int i=a;i<b;i++)
#define rep(i,n) for(int i=0;i<n;i++)
#define reprrev(i,a,b) for(int i=b-1;i>=a;i--) // [a, b)
#define reprev(i,n) reprrev(i,0,n)
typedef long long ll;
typedef unsigned long long ull;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

/* attention
    long longのシフト演算には気をつけよう
    タイポした時のデバッグが死ぬほどきつくなるので変数名は最低3字くらい使った方がいいかも
    sizeは(int)とキャストしよう
    cin.tie(0);
    ios::sync_with_stdio(false);<- これら、printfとかと併用しない方が良さそう

*/

const ll mod = 1e9+7;

void chmod(ll &M){
    if(M >= mod) M %= mod;
    else if(M < 0){
        M += (abs(M)/mod + 1)*mod;
        M %= mod;
    }
}

ll modpow(ll x, ll n){
    if(n==0) return 1;
    ll res=modpow(x, n/2);

    if(n%2==0) return res*res%mod;
    else return res*res%mod*x%mod;
}

int getl(int i, int N) { return i==0? N-1:i-1; };
int getr(int i, int N) { return i==N-1? 0:i+1; };


// 線分 ab の偏角 返り値は[-π, π]
double argument(const pair<double, double> &a, const pair<double, double> &b){
    double ax=a.first, ay=a.second, bx=b.first, by=b.second;
    return atan2(by-ay, bx-ax);
}

/* <-----------------------------------------------------------------------------------> */
/* <-----------------------------------------------------------------------------------> */
/* <-----------------------------------------------------------------------------------> */
/* <-----------------------------------------------------------------------------------> */


long double const EPS = (1e-10);
bool equal(long double const a, long double const b) { return fabs(a-b) < EPS; }

struct Point {
    long double x, y;
    Point(long double _x=0, long double _y=0) : x(_x), y(_y) {}

    Point operator + (Point const & p) const { return Point{x + p.x, y + p.y}; }
    Point & operator += (Point const & p) { x += p.x; y += p.y; return *this; }
    Point operator - (Point const & p) const { return Point{x - p.x, y - p.y}; }
    Point & operator -= (Point const & p) { x -= p.x; y -= p.y; return *this; }
    Point operator * (long double a) const { return Point{a*x, a*y}; }
    Point & operator *= (long double a) { x *= a; y *= a; return *this; }
    Point operator / (long double a) const { return Point{x/a, y/a}; }

    long double norm() { return x*x + y*y; }
    long double abs() { return sqrt(norm()); }
    
    bool operator < (Point const & p) const { return x != p.x ? x < p.x : y < p.y; }
    bool operator == (Point const & p) const { return equal(x, p.x) && equal(y, p.y); }

    void print() { cout << x << ' ' << y << "\n"; }
};
using Vector = Point;

struct Segment{
    Point p1, p2;
    Segment(Point _p1, Point _p2)
        : p1(_p1), p2(_p2) {}
};
using Line = Segment;

struct Circle{
    Point c;
    double r;
    Circle(Point _c, double _r)
        : c(_c), r(_r) {}
};
using Polygon = vector<Point>;

// 内積 外積 外積は大きさを返す
// https://mathtrain.jp/gaiseki
long double dot(Vector a, Vector b) { return a.x*b.x + a.y*b.y; }
long double cross(Vector a, Vector b) { return a.x*b.y - a.y*b.x; }

// ベクトルの直交判定　平行判定
bool isOrthogonal(Vector const & a, Vector const & b) { return equal(dot(a, b), 0.0); }
bool isOrthogonal(Point const & a1, Point const & a2, Point const & b1, Point const & b2) { return isOrthogonal(a1-a2, b1-b2); }
bool isOrthogonal(Segment const & s1, Segment const & s2) { return isOrthogonal(s1.p1 - s1.p2, s2.p1 - s2.p2); }
bool isParallel(Vector const & a, Vector const & b) { return equal(cross(a, b), 0); }
bool isParallel(Point const & a1, Point const & a2, Point const & b1, Point const & b2) { return isParallel(a1-a2, b1-b2); }
bool isParallel(Segment const & s1, Segment const & s2) { return isParallel(s1.p1-s1.p2, s2.p1-s2.p2); }

// 線分 s に対する点 p の射影
Point project(Segment const & s, Point const & p){
    Vector base = s.p2 - s.p1;
    double r = dot(p - s.p1, base) / base.norm();
    return s.p1 + base * r;
}
// 線分 s を対称軸とした点 p の線対称点
Point reflect(Segment const & s, Point const & p) { return p + (project(s, p) - p) * 2.0; }

// 線分p0-p1 に対して線分 p0-p2 が反時計回りなのか直線上なのか線分上なのか...
static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;   // p2-p0-p1
static const int ONLINE_FRONT = -2; // p0-p1-p2
static const int ON_SEGMENT = 0;    // p0-p2-p1
int ccw(Point const & p0, Point const & p1, Point const & p2){
    Vector a = p1 - p0, b = p2 - p0;
    if(cross(a, b) > EPS) return COUNTER_CLOCKWISE;
    if(cross(a, b) < -EPS) return CLOCKWISE;
    if(dot(a, b) < -EPS) return ONLINE_BACK;
    if(a.norm() < b.norm()) return ONLINE_FRONT;
    return ON_SEGMENT;
}

// 線分 p1-p2 と線分 p3-p4 の交差判定（交点を持てば true）
bool intersect(Point const & p1, Point const & p2, Point const & p3, Point const & p4){
    return (ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 && ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0);
}
bool intersect(Segment const & s1, Segment const & s2) { return intersect(s1.p1, s1.p2, s2.p1, s2.p2); }

// 点と直線の距離
long double getDistanceLP(Line const & l, Point const & p) {
    return abs(cross(l.p2-l.p1, p-l.p1) / (l.p2-l.p1).abs());
}

// 点と線分の距離
long double getDistanceSP(Segment s, Point p) {
    if (dot(s.p2-s.p1, p-s.p1) < 0.0) return (p-s.p1).abs();
    if (dot(s.p1-s.p2, p-s.p2) < 0.0) return (p-s.p2).abs();
    return getDistanceLP(s, p);
}

// 線分と線分の距離
long double getDistance(Segment s1, Segment s2) {
    if (intersect(s1, s2)) return 0.0;
    return min(min(getDistanceSP(s1, s2.p1), getDistanceSP(s1, s2.p2)), min(getDistanceSP(s2, s1.p1), getDistanceSP(s2, s1.p2)));
}

// 線分と線分の交点　交点がある時
Point getCrossPoint(Segment s1, Segment s2) {
    Vector base = s2.p2 - s2.p1;
    long double d1 = abs(cross(base, s1.p1 - s2.p1));
    long double d2 = abs(cross(base, s1.p2 - s2.p1));
    long double t = d1 / (d1 + d2);
    return s1.p1 + (s1.p2 - s1.p1) * t;
}

//　円 c と直線 l の交点
pair<Point, Point> getCrossPoints(Circle c, Line l) {
    assert(getDistanceLP(l, c.c) < c.r + EPS);
    Vector pr = project(l, c.c);
    Vector e = (l.p2 - l.p1) / (l.p2 - l.p1).abs();
    long double base = sqrt(c.r*c.r - (pr-c.c).norm());
    return make_pair(pr + e*base, pr - e*base);
}

long double arg(Vector p) { return atan2(p.y, p.x); }
// a, r -> (rcos(a), rsin(a))
Vector polar(long double a, long double r) { return Point(a*cos(r), a*sin(r)); }

pair<Point, Point> getCrossPoints(Circle c1, Circle c2) {
    assert((c1.c - c2.c).norm() < (c1.r + c2.r) * (c1.r + c2.r) + EPS);
    long double d2 = (c1.c - c2.c).norm();
    long double a = acos((c1.r*c1.r + d2 - c2.r*c2.r) / (2*c1.r*sqrt(d2)));
    long double t = arg(c2.c - c1.c);
    return make_pair(c1.c + polar(c1.r, t+a), c1.c + polar(c1.r, t-a));
}


int main(){
    cin.tie(nullptr);
    ios::sync_with_stdio(false);

    using triple = tuple<Point, int, int>;
    int n; cin >> n;
    vector<long double> x(n), y(n);
    rep(i, n) cin >> x[i] >> y[i];
    
    long double ok = 10000; long double ng = 0.0;
    auto check = [&](long double r) {
        if (r<EPS) return true;
        vector<triple> pij;
        rep(i, n) rep(j, n) if (i!=j) {
            Circle c1(Point(x[i], y[i]), r), c2(Point(x[j], y[j]), r);
            if ((c1.c - c2.c).norm() >= (c1.r + c2.r) * (c1.r + c2.r) + EPS) return false;
            auto pa = getCrossPoints(c1, c2);
            pij.push_back(make_tuple(pa.first, i, j));
            pij.push_back(make_tuple(pa.second, i, j));
        }
        for(auto ele: pij) {
            Point p; int i; int j; tie(p, i, j) = ele;
            bool ok = true;
            rep(k, n) if (k!=i && k!=j) {
                if ((p - Point(x[k], y[k])).norm() > r*r) { ok = false; break; }
            }
            if (ok) return true;
        }
        return false;
    };
    rep(_, 200) {
        long double mid = (ok+ng) / 2;
        (check(mid)? ok:ng) = mid;
    }
    cout << fixed << setprecision(15) << ok << endl;
    return 0;
}


Measured memory_bytes: 940