#include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(arg),key)-begin(arg)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))

using namespace std;

using R=long double;
const R EPS = 1E-11; //[-1000:1000]->EPS=1e-8
const R INF = 1E40;
constexpr R PI = acos(R(-1));
inline int sgn(const R& r){ return (r > EPS) - (r < -EPS);}
inline R sq(R x){return sqrt(max<R>(x,0.0));}

using P=complex<R>;
using VP=vector<P>;
using L=struct{P s,t;};
using VL=vector<L>;
using C=struct{P c;R r;};
using VC=vector<C>;

constexpr P O = P(0,0);
istream& operator >> (istream& is,P& p){ R x,y;is >> x >> y; p=P(x,y); return is;}
ostream& operator << (ostream& os,P& p){ os << real(p) << " " << imag(p); return os;}

namespace std{
	bool operator <  (const P& a,const P& b){ return sgn(real(a-b))?real(a-b)<0:sgn(imag(a-b))<0;}
	bool operator == (const P& a,const P& b){ return sgn(real(a-b))==0 && sgn(imag(a-b))==0;}
}
inline bool cmp_y(const P& a, const P& b){return sgn(imag(a-b)) ? imag(a-b)<0 : sgn(real(a-b))<0;}
inline bool cmp_a(const P& a, const P& b){return sgn(arg(a)-arg(b)) ? arg(a)-arg(b)<0 : sgn(norm(a)-norm(b))<0;}
bool operator <  (const L& a,const L& b){ return a.s==b.s?a.t<b.t:a.s<b.s;}
bool operator == (const L& a,const L& b){ return a.s==b.s&&a.t==b.t;}

//?????? dot ?????? det
inline R dot(P o,P a,P b){a-=o,b-=o; return real(conj(a)*b);}
inline R det(P o,P a,P b){a-=o,b-=o; return imag(conj(a)*b);}
inline R dat(P o,P a,P b){a-=o,b-=o; return imag(a*b);}

inline P vec(L l){return l.t-l.s;}

// ?°???± verify AOJ CGL_1_A
P proj(P o,P a,P b){ a-=o,b-=o; return a*real(b/a);}
P proj(L l,P p){ return l.s+proj(l.s,l.t,p);}
// ????°? verify AOJ CGL_1_B
P refl(L l,P p){ return R(2.0)*proj(l,p)-p;}
// CCW verify AOJ CGL_1_C
enum CCW{ LEFT = 1,RIGHT = 2,BACK = 4,FRONT = 8,ON = 16};
inline int ccw(P o,P a, P b) {//???a??¨???b???????????????????????????
	if (sgn(det(o,a,b)) > 0) return LEFT;    // counter clockwise
	if (sgn(det(o,a,b)) < 0) return RIGHT;   // clockwise
	if (sgn(dot(o,a,b)) < 0) return BACK;    // b--base--a on line
	if (sgn(norm(a-o)-norm(b-o)) < 0) return FRONT;   // base--a--b on line
	return ON;// base--b--a on line  a??¨b????????????????????????
}

// ?????´ ?????? verify AOJ CGL_2_A
bool vertical(L a, L b) {return sgn(dot(O,vec(a),vec(b)))==0;}
bool parallel(L a, L b) {return sgn(det(O,vec(a),vec(b)))==0;}

// ????????´????????? 
bool eql(L a,L b){ return (parallel(a,b) && sgn(det(a.s,a.t,b.s))==0);}

// ???????????????verify AOJ CGL_2_B ???????????????????????´??????1,????????´??????0
bool ill(L a,L b){ return parallel(a,b)==false;}
bool ils(L l,L s,int end=0){ return sgn(det(l.s,l.t,s.s)*det(l.s,l.t,s.t))<=-end;}
bool iss(L a,L b,int end=0){
	int s1=ccw(a.s,a.t,b.s)|ccw(a.s,a.t,b.t);
	int s2=ccw(b.s,b.t,a.s)|ccw(b.s,b.t,a.t);
	if(end) return (s1&s2)==(LEFT|RIGHT);
	return (s1|s2)&ON || (s1&s2)==(LEFT|RIGHT);
}

// ?????? verify AOJ CGL_2_C
P cross(L a,L b){
	R s1=det(a.s,b.s,b.t);
	R s2=s1+det(a.t,b.t,b.s);
	return a.s+s1/s2*(a.t-a.s);
}
	
// ?????¢ verify AOJ CGL_2_D
R dlp(L l,P p){return abs(det(l.s,l.t,p))/abs(vec(l));}
R dsp(L s,P p){
	if(sgn(dot(s.s,s.t,p))<=0) return abs(p-s.s);
	if(sgn(dot(s.t,s.s,p))<=0) return abs(p-s.t);
	return dlp(s,p);
}
R dll(L a,L b){return ill(a,b)?0:dlp(a,b.s);}
R dls(L l,L s){return ils(l,s)?0:min(dlp(l,s.s),dlp(l,s.t));}
R dss(L a,L b){return iss(a,b)?0:min({dsp(a,b.s),dsp(a,b.t),dsp(b,a.s),dsp(b,a.t)});}

// ????§???¢
// ??¢??? Verify AOJ 1100 CGL_3_A
R area(const VP& pol){
	int n=pol.size();
	R sum=0;
	rep(i,n) sum+=det(O,pol[i],pol[(i+1)%n]);
	return abs(sum/2.0);
}

// ???????§???¢????????? verify CGL_3_B
bool is_convex(const VP& pol){
	int n=pol.size();
	rep(i,n)if(ccw(pol[(i+n-1)%n],pol[i],pol[(i+1)%n])==RIGHT) return false;
	return true;
}

// ????§???¢??????????????? ?????? 2 ?????? 1 ???????????? 0???(???????§???¢??????) verify AOJ CGL_3-C
int in_polygon(const VP& pol, const P& p){
	int n=pol.size(),res=0;
	rep(i,n){
		if(ccw(pol[i],pol[(i+1)%n],p)==ON) return 1;
		bool f=sgn(imag(p-pol[i]))>=0;
		bool s=sgn(imag(p-pol[(i+1)%n]))<0;
		int sign=sgn(imag(pol[(i+1)%n]-pol[i]));
		bool can=sgn(sign*det(pol[i],pol[(i+1)%n],p))>0; // (a*d-b*c)*b
		if(can&&f==s) res+=(2*f-1);
	}
	return res?2:0;
}

// ????§???¢??????????????????(???????§???¢??????) Verify AOJ 2514
bool in_polygon(const VP& pol, const L& l){
	VP check{l.s,l.t};
	int n=pol.size();
	rep(i,n){
		L edge={pol[i],pol[(i+1)%n]};
		if(iss(l,edge)) check.push_back(cross(l,edge));
	}
	sort(_all(check));
	n=check.size();
	rep(i,n-1){
		P m=(check[i]+check[i+1])/R(2.0);
		if(in_polygon(pol,m)==false) return false;
	}
	return true;
}

// convex_hull Verify AOJ CGL_4_A ?????????????????????????????´??????1,??????????????´??????0
VP convex_hull(VP pol,int edge=0){
	int n=pol.size(),k=0;
	sort(_all(pol));
	VP res(2*n);

	//??\??????while????????????????????? ???????????????????????????????????? >=0 ????????????>=1
	// down
	rep(i,n){
		while(k>1&&sgn(det(O,res[k-1]-res[k-2],pol[i]-res[k-1]))>=edge) k--;
		res[k++]=pol[i];
	}
	// up
	int t=k;
	rrep(i,n-1){
		while(k>t&&sgn(det(O,res[k-1]-res[k-2],pol[i]-res[k-1]))>=edge) k--;
		res[k++]=pol[i];
	}
	res.resize(k-1);
	return res;
}

// farthest point pair Verify AOJ CGL_4_B
R fpp(VP pol){
	// if(!is_convex(pol)) pol=convex_hull(pol);
	int n=pol.size();
	R res=0.0;
	if(n<=10){
		rep(j,n)rep(i,j) res=max(res,abs(pol[i]-pol[j]));
		return res;
	}
	
	int i=min_element(_all(pol))-begin(pol);
    int j=max_element(_all(pol))-begin(pol);
    
    rep(k,2*n){
		res=max(res,abs(pol[i]-pol[j]));
		if(sgn(det(O,pol[(i+1%n)]-pol[i],pol[(j+1%n)]-pol[j]))<0)
			i=(i+1)%n;
		else
			j=(j+1)%n;
	}
	return res;
}

// ???????????? verify AOJ CGL_4_C
VP convex_cut(const VP& pol,const L& l) {
	VP res;
	int n=pol.size();
	rep(i,n){
		P a = pol[i],b=pol[(i+1)%n];
		if(ccw(l.s,l.t,a)!=RIGHT)res.push_back(a);
		if((ccw(l.s,l.t,a)|ccw(l.s,l.t,b))==(LEFT|RIGHT)) res.push_back(cross({a,b},l));
	}
	return res;
}

// closest point pair Verify AOJ CGL_5_A
R cpp(VP a,int flag=1){
	if(flag) sort(_all(a));
	int n=a.size(),m=n/2;
	if(n<=1) return INF;
	VP b(begin(a),begin(a)+m),c(begin(a)+m,end(a)),e;
	R x=real(a[m]),d=min(cpp(b,0),cpp(c,0));
	sort(_all(a),cmp_y);
	rep(i,n){
		if(abs(real(a[i])-x)>=d) continue;	
		rep(j,e.size()){
			if(imag(a[i]-e[e.size()-1-j])>=d) break;
			d=min(d,abs(a[i]-e[e.size()-1-j]));
		}
		e.push_back(a[i]);
	}
	return d;
}

// ???
// Verify AOJ 1183
enum RCC{IN=1,ON_IN=2,ISC=4,ON_OUT=8,OUT=16,ONS=10};
int rcc(C a,C b){
	R d=abs(a.c-b.c);
	int res=0;
	if(a.r+b.r< d) return OUT;
	if(a.r+b.r==d) return ON_OUT;
	if(abs(a.r-b.r)<d) return ISC;
	if(abs(a.r-b.r)==d) return ON_IN;
	return IN;
}

// ?????¢??£???????????????
bool icp(C c,P p,int end=0){return sgn(abs(p-c.c)-c.r)<=-end;}
bool ics(C c,L l,int end=0){return sgn(dsp(l,c.c)-c.r)<=-end;}
bool icsc(C c,L l){return ics(c,l) && sgn(max(abs(l.s-c.c),abs(l.t-c.c))-c.r)<=0;}

//?????¨??´????????????
// Verify AOJ CGL_7_D
VP pcl(C c, L l) {
	P h=proj(l,c.c);
	P e=(l.t-l.s)/abs(l.t-l.s)*sq(norm(c.r)-norm(h-c.c));
	return VP{h-e,h+e};
}
//2??????????????????
// Verify AOJ CGL_7_E
VP pcc(C a,C b){
	P d=b.c-a.c;
	P w=(norm(d)+norm(a.r)-norm(b.r))/(2.0*norm(d))*d;
	P e=w*P(0,1);
	return pcl(a,{a.c+w-e,a.c+w+e}); 
}

// ????????\???
// Verify AOJ 2001
L tangent(C c,R t){
	P p=c.c+polar(c.r,t);
	P d=polar(c.r,t)*P(0,1);
	return L{p-d,p+d};
}

// ????????±?????\???
// Verify AOJ 2001
VL common_tangent(C a,C b){
	VL res;
	R d=arg(b.c-a.c),i=acos((a.r+b.r)/abs(b.c-a.c)),o=acos((a.r-b.r)/abs(b.c-a.c));
	int r=rcc(a,b);
	//??±????????\???
	if(r==OUT){
		res.push_back(tangent(a,d+i));
		res.push_back(tangent(a,d-i));
	}
	// ??±????????\???
	if(r>=ISC){
		res.push_back(tangent(a,d+o));
		res.push_back(tangent(a,d-o));
	}
	//??\????????±???????????\???
	if(r&ONS) res.push_back(tangent(a,d));
	return res;
}

// under not verify
// segments arrangement
const int vmax=10010;
struct node{int to;R cost;};
vector<node> graph[vmax];

void segments_arrangement(const vector<L> &seg, vector<P> &point){
	int n=seg.size();
	rep(i,n){
		point.push_back(seg[i].s);
		point.push_back(seg[i].t);
		rep(j,i) if(iss(seg[i],seg[j])) point.push_back(cross(seg[i],seg[j]));
	}
	uniq(point);
	rep(i,n){
		using key=pair<R,int>;
		vector<key> ary;
		rep(j,point.size()) if(ccw(seg[i].s,seg[i].t,point[j])==ON) ary.push_back(key(norm(point[j]-seg[i].s),j));
		sort(_all(ary));
		rep(j,int(ary.size()-1)){
			int a=ary[j].second,b=ary[j+1].second;
			graph[a].push_back({b,abs(point[a]-point[b])});
			graph[b].push_back({a,abs(point[a]-point[b])});
		}
	}
	return;
}

// ????????????????????????
VL merge(VL l) {
	int n=l.size();
	rep(i,n) if(l[i].t<l[i].s) swap(l[i].s,l[i].t);
	sort(_all(l));
	rep(i,n)rep(j,i){
		if(iss(l[i],l[j],0)&&!iss(l[i],l[j],1)){
			if(abs(l[i].t-l[j].s)>abs(l[j].t-l[j].s)) l[j].t = l[i].t;
			l.erase(begin(l)+i--);
			break;
		}
	}
	return l;
}

// ???????????£??¨????????°?
// ????§???¢???????????????????????????????????????
VP normalize_polygon(VP pol){
	int n=pol.size();
	rep(i,n) if(ccw(pol[(i+n-1)%n],pol[i],pol[(i+1)%n])==ON) pol.erase(begin(pol)+i--);
	return pol;
}

L bisector(P a, P b){
	P mid=(a+b)/P(2,0);
	return L{mid, mid+(b-a)*P(0,1)};
}

VP voronoi_cell(VP pol,VP v,int s){
	rep(i,v.size()) if(i!=s) pol=convex_cut(pol,bisector(v[s],v[i]));
	return pol;
}

// minimum_circle

// dual graph
/*
vector<Pol> dual(vector<L> s) {
  vector<P> vp;
  vector<vector<int> > edge = sArr(s, vp);
  vector<vector<bool> > used(edge.size());
  rep (i, edge.size()) rep (j, edge[i].size()) used[i].push_back(false);
  vector<Pol> vpol;
  rep (i, edge.size()) rep (j, edge[i].size()) if (!used[i][j]) {
    Pol pol;
    pol.push_back(vp[i]);
    used[i][j] = true;
    int pre = i, now = edge[i][j];
    while (now != i) {
      pol.push_back(vp[now]);
      D a = -4;
      int next = -1;
      rep (k, edge[now].size()) {
    D aa = arg(vp[now], (D)2 * vp[now] - vp[pre], vp[edge[now][k]]);
    if (!sig(aa, PI)) aa = -PI;
    if (a < aa) {
      a = aa;
      next = k;
    }
      }
      used[now][next] = true;
      pre = now;
      now = edge[pre][next];
    }
    vpol.push_back(pol);
  }
  return vpol;
}
*/

// ?????¨????§???¢?????±?????¨?????¢???
/*
D aCTnc(D r, P p1, P p2) {return sig(abs((p1 + p2) / (D)2), r) <= 0 ? ep(p1, p2) / 2 : r * r * arg(0, p1, p2) / 2;}
D aCT(D r, P p1, P p2) {
  if (!sig(r) || near(0, p1) || near(0, p2) || near(p1, p2)) return 0;
  pair<P, P> pp = pCL((C){0, r}, (L){p1, p2});
  if ((p1 < pp.first) != (pp.first < p2) && (p1 < pp.second) != (pp.second < p2)) return aCTnc(r, p1, p2);
  return aCTnc(r, p1, pp.first) + aCTnc(r, pp.first, pp.second) + aCTnc(r, pp.second, p2);
}
D aCPol(C c, Pol pol) {D res = 0; rep (i, pol.size()) res += aCT(c.r, pol[i] - c.c, at(pol, i + 1) - c.c); return res;}
*/


// hough T
// ??¢?????£?????????
// Delaunay Triangle
// Kd-Tree
// ???

int main(void){
	int n;
	cin >> n;
	VP pol;
	rep(i,n){
		P p;
		cin >> p;
		pol.push_back(p);
	}
	cout.precision(10);
	cout << fixed << fpp(pol) << endl;
	return 0;
}

Measured memory_bytes: 8264