/* #region Head */

#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using ull = unsigned long long;
using ld = long double;
using pll = pair<ll, ll>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vld = vector<ld>;
using vvd = vector<vld>;
using vs = vector<string>;
using vvs = vector<vs>;

#define REP(i, m, n) for (ll i = (m), i##_len = (ll)(n); i < i##_len; ++(i))
#define REPM(i, m, n) for (ll i = (m), i##_max = (ll)(n); i <= i##_max; ++(i))
#define REPR(i, m, n) for (ll i = (m), i##_min = (ll)(n); i >= i##_min; --(i))
#define REPD(i, m, n, d) for (ll i = (m), i##_len = (ll)(n); i < i##_len; i += (d))
#define REPMD(i, m, n, d) for (ll i = (m), i##_max = (ll)(n); i <= i##_max; i += (d))
#define REPI(itr, ds) for (auto itr = ds.begin(); itr != ds.end(); itr++)
#define ALL(x) begin(x), end(x)
#define SIZE(x) ((ll)(x).size())

constexpr ll INF = 1'010'000'000'000'000'017LL;
constexpr ll MOD = 1'000'000'007LL; // 1e9 + 7
constexpr double EPS = 1e-12;
constexpr double PI = 3.14159265358979323846;

// vector入力
template <typename T>
istream &operator>>(istream &is, vector<T> &vec)
{
    for (T &x : vec)
        is >> x;
    return is;
}

// vector出力
template <typename T>
ostream &operator<<(ostream &os, vector<T> &vec)
{
    ll len = SIZE(vec);
    os << "{";
    for (int i = 0; i < len; i++)
        os << vec[i] << (i == len - 1 ? "" : ", ");
    os << "}";
    return os;
}

// pair入力
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &pair_var)
{
    is >> pair_var.first >> pair_var.second;
    return is;
}

// pair出力
template <typename T, typename U>
ostream &operator<<(ostream &os, pair<T, U> &pair_var)
{
    os << "(" << pair_var.first << ", " << pair_var.second << ")";
    return os;
}

// map出力
template <typename T, typename U>
ostream &operator<<(ostream &os, map<T, U> &map_var)
{
    os << "{";
    REPI(itr, map_var)
    {
        os << *itr;
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}

// set 出力
template <typename T>
ostream &operator<<(ostream &os, set<T> &set_var)
{
    os << "{";
    REPI(itr, set_var)
    {
        os << *itr;
        itr++;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}

// dump
#define DUMPOUT cerr
void dump_func()
{
    DUMPOUT << endl;
}
template <class Head, class... Tail>
void dump_func(Head &&head, Tail &&... tail)
{
    DUMPOUT << head;
    if (sizeof...(Tail) > 0)
    {
        DUMPOUT << ", ";
    }
    dump_func(move(tail)...);
}

// _max の終端．
template <class Head>
ll _max(Head &&head)
{
    return head;
}
// 最大値を求める．max({}) の代わり．これにしないと vscode が壊れる．
template <class Head, class... Tail>
ll _max(Head &&head, Tail &&... tail)
{
    return max((ll)head, _max((tail)...));
}

// _min の終端．
template <class Head>
ll _min(Head &&head)
{
    return head;
}
// 最小値を求める．min({}) の代わり．これにしないと vscode が壊れる．
template <class Head, class... Tail>
ll _min(Head &&head, Tail &&... tail)
{
    return min((ll)head, _min((tail)...));
}

// chmax (更新「される」かもしれない値が前)
template <typename T, typename U, typename Comp = less<>>
bool chmax(T &xmax, const U &x, Comp comp = {})
{
    if (comp(xmax, x))
    {
        xmax = x;
        return true;
    }
    return false;
}

// chmin (更新「される」かもしれない値が前)
template <typename T, typename U, typename Comp = less<>>
bool chmin(T &xmin, const U &x, Comp comp = {})
{
    if (comp(x, xmin))
    {
        xmin = x;
        return true;
    }
    return false;
}

// container 内の最初の element のインデックスを探す
template <class Container>
ll indexof(const Container &container, const typename Container::value_type &element)
{
    auto iter = find(container.begin(), container.end(), element);
    size_t index = distance(container.begin(), iter);
    if (index == container.size())
    {
        index = -1;
    }
    return index;
}

// ローカル用
#define DEBUG_

#ifdef DEBUG_
#define DEB
#define dump(...)                                                       \
    DUMPOUT << "  " << string(#__VA_ARGS__) << ": "                     \
            << "[" << to_string(__LINE__) << ":" << __FUNCTION__ << "]" \
            << endl                                                     \
            << "    ",                                                  \
        dump_func(__VA_ARGS__)
#else
#define DEB if (false)
#define dump(...)
#endif

struct AtCoderInitialize
{
    static constexpr int IOS_PREC = 15;
    static constexpr bool AUTOFLUSH = false;

    AtCoderInitialize()
    {
        ios_base::sync_with_stdio(false);
        cin.tie(nullptr);
        cout.tie(nullptr);
        cout << fixed << setprecision(IOS_PREC);
        if (AUTOFLUSH)
            cout << unitbuf;
    }
} ATCODER_INITIALIZE;

/* #endregion */

// // ここから幾何テンプレート
using P = complex<ld>; // 2次元平面上の点
using G = vector<P>;
const ld pi = acos(-1);

ld cross(const P &a, const P &b) { return a.real() * b.imag() - a.imag() * b.real(); }
ld dot(const P &a, const P &b) { return a.real() * b.real() + a.imag() * b.imag(); }

/*
                    CCW

 -- BEHIND -- [a -- ON -- b] --- FRONT --

                    CW
 */
enum CCW_RESULT
{
    CCW = +1,
    CW = -1,
    BEHIND = +2,
    FRONT = -2,
    ON = 0
};
int ccw(P a, P b, P c)
{
    b -= a;
    c -= a;
    if (cross(b, c) > EPS)
        return CCW; // counter clockwise
    if (cross(b, c) < -EPS)
        return CW; // clockwise
    if (dot(b, c) < 0)
        return BEHIND; // c--a--b on line
    if (norm(b) < norm(c))
        return FRONT; // a--b--c on line
    return ON;
}

bool operator<(const P &a, const P &b)
{
    return abs(real(a) - real(b)) > EPS ? real(a) < real(b) : imag(a) < imag(b);
}

// 2次元平面上の直線を表す構造体
struct L : public vector<P>
{
    void regist(const P &a, const P &b)
    {
        begin()[0] = a;
        begin()[1] = b;
    }
    L(const P &a = P(), const P &b = P()) : vector<P>(2)
    {
        regist(a, b);
    }

    // Ax + By + C = 0
    L(ld A, ld B, ld C) : vector<P>(2)
    {
        if (abs(A) < EPS && abs(B) < EPS)
            abort();
        else if (abs(A) < EPS)
            regist(P(0, -C / B), P(1, -C / B));
        else if (abs(B) < EPS)
            regist(P(-C / A, 0), P(-C / A, 1));
        else
            regist(P(0, -C / B), P(-C / A, 0));
    }
};

// 2次元平面上の円を表す構造体
struct Circle
{
    P p;
    ld r;
    Circle(const P &p = 0, ld r = 0) : p(p), r(r) {}
};
// 2次元平面上の円を表す構造体，ただし半径は2乗で保持する
struct Circle2
{
    P p;
    ld r2; // 半径の2乗
    Circle2(const P &p = 0, ld r2 = 0) : p(p), r2(r2) {}
    ld r() { return sqrt(r2); } // 半径を返す
};

// 最小包含円テンプレート
template <class iter>
Circle2 min_ball(iter left, iter right, int seed = 1333)
{
    const int n = right - left; // 点の個数

    assert(n >= 1);
    if (n == 1)
    {
        return Circle2(*left, ld(0));
    }

    mt19937 mt(seed);
    shuffle(left, right, mt); // シャッフルすることで平均計算量 O(n) に近づける
    // std::random_shuffle(left, right); // simple but deprecated

    iter ps = left; // ps[i] := i 番目の点

    // 3頂点を円周に持つ最小の円を求める
    auto make_circle_3 = [](const P &a, const P &b, const P &c) -> Circle2 {
        ld A = std::norm(b - c),
           B = std::norm(c - a),
           C = std::norm(a - b),
           S = cross(b - a, c - a);
        P p = (A * (B + C - A) * a + B * (C + A - B) * b + C * (A + B - C) * c) / (4 * S * S);
        ld r2 = std::norm(p - a);
        return Circle2(p, r2);
    };

    // 2頂点を円周に持つ最小の円を求める
    auto make_circle_2 = [](const P &a, const P &b) -> Circle2 {
        P c = (a + b) / (ld)2;
        ld r2 = std::norm(a - c);
        return Circle2(c, r2);
    };

    // ある点が，ある円の内部または周上にあるときに true を返す
    // 最終的には，「入るかどうか」ではなく「円の半径の数値」が欲しいので，EPS を足すという仕様でよい
    auto in_circle = [](const P &a, const Circle2 &c) -> bool {
        return std::norm(a - c.p) <= c.r2 + EPS;
    };

    // 初期円
    Circle2 c = make_circle_2(ps[0], ps[1]);

    // MiniDisc
    for (int i = 2; i < n; ++i)
    {
        if (in_circle(ps[i], c))
            continue; // 点 i は円の内部に入っているので，c は更新しない

        // MiniDiscWithPoint
        c = make_circle_2(ps[0], ps[i]);
        for (int j = 1; j < i; ++j)
        {
            if (in_circle(ps[j], c))
                continue;

            // MiniDiscWith2Points
            c = make_circle_2(ps[i], ps[j]);
            for (int k = 0; k < j; ++k)
            {
                if (in_circle(ps[k], c))
                    continue;
                c = make_circle_3(ps[i], ps[j], ps[k]);
            }
        }
        // この時点で，円 c は点 0, 1, ..., i を含む最小の円になっている
    }
    return c;
}

/**
Problem
 */
void solve()
{
    ll n;
    cin >> n;
    vld x(n), y(n);
    REP(i, 0, n)
    {
        cin >> x[i] >> y[i];
    }

    vector<P> points(n);
    REP(i, 0, n)
    {
        points[i] = P(x[i], y[i]);
    }

    Circle2 c = min_ball(ALL(points));
    cout << c.r() << endl;
}

/**
 * エントリポイント．
 * @return 0.
 */
int main()
{
    solve();
    return 0;
}


Measured memory_bytes: 256