fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());
    let n: usize = sc.read();
    let mut ps = vec![];
    for _ in 0..n {
        let x: f64 = sc.read();
        let y: f64 = sc.read();
        ps.push(Point { x: x, y: y });
    }

    let c = mini_circle(&ps);
    println!("{}", c.1.sqrt());
}

fn mini_circle(ps: &[Point<f64>]) -> (Point<f64>, f64) {
    let n = ps.len();
    assert!(n >= 2);

    let mut c = make_circle2(ps[0], ps[1]);
    for i in 2..n {
        if is_included(ps[i], c) {
            continue;
        }
        c = make_circle2(ps[0], ps[i]);
        for j in 1..i {
            if is_included(ps[j], c) {
                continue;
            }
            c = make_circle2(ps[i], ps[j]);
            for k in 0..j {
                if is_included(ps[k], c) {
                    continue;
                }
                c = make_circle3(ps[i], ps[j], ps[k]);
            }
        }
    }
    c
}

fn make_circle3(a: Point<f64>, b: Point<f64>, c: Point<f64>) -> (Point<f64>, f64) {
    let ea = (b - c).norm();
    let eb = (c - a).norm();
    let ec = (a - b).norm();
    let s = (b - a).det(&(c - a));

    let p = (a * ea * (eb + ec - ea) + b * eb * (ec + ea - eb) + c * ec * (ea + eb - ec))
        / (s * s * 4.0);
    let r2 = (p - a).norm();
    (p, r2)
}

fn make_circle2(a: Point<f64>, b: Point<f64>) -> (Point<f64>, f64) {
    let c = (a + b) / 2.0;
    let r2 = (a - c).norm();
    (c, r2)
}

fn is_included(a: Point<f64>, circle: (Point<f64>, f64)) -> bool {
    let (center, r2) = circle;
    (a - center).norm() <= r2
}

pub struct Point<T> {
    x: T,
    y: T,
}

impl<T> Copy for Point<T> where T: Copy {}
impl<T> Clone for Point<T>
where
    T: Clone,
{
    fn clone(&self) -> Point<T> {
        Point {
            x: self.x.clone(),
            y: self.y.clone(),
        }
    }
}

impl<T> std::ops::Sub for Point<T>
where
    T: std::ops::Sub<Output = T>,
{
    type Output = Point<T>;
    fn sub(self, other: Point<T>) -> Point<T> {
        Point {
            x: self.x - other.x,
            y: self.y - other.y,
        }
    }
}

impl<T> std::ops::Mul<T> for Point<T>
where
    T: Copy + std::ops::Mul<Output = T>,
{
    type Output = Point<T>;
    fn mul(self, rhs: T) -> Point<T> {
        Point {
            x: self.x * rhs,
            y: self.y * rhs,
        }
    }
}

impl<T> std::ops::Div<T> for Point<T>
where
    T: Copy + std::ops::Div<Output = T>,
{
    type Output = Point<T>;
    fn div(self, rhs: T) -> Point<T> {
        Point {
            x: self.x / rhs,
            y: self.y / rhs,
        }
    }
}

impl<T> std::ops::Add<Point<T>> for Point<T>
where
    T: std::ops::Add<Output = T>,
{
    type Output = Point<T>;

    fn add(self, rhs: Point<T>) -> Point<T> {
        Point {
            x: self.x + rhs.x,
            y: self.y + rhs.y,
        }
    }
}

impl<T> Point<T>
where
    T: Copy + std::ops::Mul<Output = T> + std::ops::Sub<Output = T> + std::ops::Add<Output = T>,
{
    pub fn det(&self, other: &Point<T>) -> T {
        self.x * other.y - self.y * other.x
    }
    pub fn norm(&self) -> T {
        self.x * self.x + self.y * self.y
    }
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> IO<R, W> {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: std::ops::Deref<Target = str>>(&mut self, s: S) {
        use std::io::Write;
        self.1.write(s.as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


Measured memory_bytes: 4352