using namespace std;
#include <set>
#include <map>
#include <list>
#include <deque>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <bitset>
#include <utility>
#include <algorithm>
#define pb push_back
#define sz size
#define f first
#define s second
#define II inline
#define ll long long
#define db double
#define FOR(i,a,b) for(int i=a;i<=b;++i)
#define all(v) v.begin() , v.end()
#define CC(v) memset((v),0,sizeof((v)))
#define CP(v,w) memcpy((v),(w),sizeof((w)))
#define mp make_pair
#define IN "adapost.in"
#define OUT "adapost.out"
#define N_MAX 1<<9
#define Dimp 1
typedef vector<int> VI;
typedef pair<int,int> pi;
typedef vector<string> VS;
vector< pair<db,db> > Q1(N_MAX),Q2(N_MAX);
vector<VI> A(1<<10);
int S,E,N,T[1<<10],L[N_MAX],R[N_MAX],C[1<<10][1<<10];
db D[1<<10][1<<10];
db Q[1<<18],Dist[1<<10];
bool viz[1<<10];
II void scan()
{
freopen(IN,"r",stdin);
freopen(OUT,"w",stdout);
scanf("%d",&N);
double x,y;
FOR(i,1,N)
{
scanf("%lf%lf\n",&x,&y);
// x *= 1000;y *= 1000;
Q1[i] = mp(x,y);
}
FOR(i,1,N)
{
scanf("%lf%lf\n",&x,&y);
// x *= 1000;y *= 1000;
Q2[i] = mp(x,y);
}
}
II db dist(pair<db,db> x,pair<db,db> y)
{
return 1LL * (x.f - y.f) * (x.f - y.f) + 1LL * (x.s - y.s) * (x.s - y.s);
}
II bool DF(int nod)
{
if(viz[nod])
return false;
viz[nod] = true;
for(VI::iterator it=A[nod].begin();it != A[nod].end();++it)
if(!L[*it])
{
L[*it] = nod;
R[nod] = *it;
return true;
}
for(VI::iterator it=A[nod].begin();it != A[nod].end();++it)
if(DF( L[*it] ) )
{
L[*it] = nod;
R[nod] = *it;
return true;
}
return false;
}
II bool cuplaj(db dist)
{
CC(L),CC(R);
FOR(i,1,N)
{
A[i].resize(0);
FOR(j,1,N)
if(D[i][j] <= dist)
A[i].pb(j);
}
bool ok(true);
for(;ok;)
{
ok = false;
CC(viz);
FOR(i,1,N)
if(!R[i])
ok |= DF(i);
}
int rez(0);
FOR(i,1,N)
if(R[i])
++rez;
return rez == N;
}
struct comp{ bool operator() (int i,int j) {return Dist[i] > Dist[j];} };
priority_queue<int,VI,comp> Qh;
II bool Dijkastra()
{
memset(Dist,100,sizeof(Dist) );
int G[1<<10]={0};
CC(T);
Dist[S] = 0;
Qh.push(S);
++G[S];
for(int nod;!Qh.empty();)
{
nod = Qh.top();
--G[nod];
Qh.pop();
if(G[nod])
continue;
for(VI::iterator it=A[nod].begin();it != A[nod].end();++it)
if(C[nod][*it] && Dist[*it] > Dist[nod] + D[nod][*it])
{
Dist[*it] = Dist[nod] + D[nod][*it];
T[*it] = nod;
Qh.push(*it);
++G[*it];
}
}
return T[E];
}
II db distf(db dist)
{
db aux = (db)dist / (db)Dimp;
return sqrt(aux);
}
II void flow(int m)
{
FOR(i,1,N)
FOR(j,1,N)
if(D[i][j] <= Q[m])
{
A[i].pb(j + N);
A[j + N].pb(i);
D[i][j+N] = D[i][j];
D[j+N][i] = -D[i][j];
C[i][j+N] = 1;
}
S = N+N+1;
E = N+N+2;
FOR(i,1,N)
{
A[S].pb(i);
A[i].pb(S);
A[E].pb(i+N);
A[i+N].pb(E);
C[S][i] = 1,
C[i+N][E] = 1;
}
for(Dijkastra();Dijkastra();)
for(int nod = E;T[nod];--C[ T[nod] ][nod],++C[nod][ T[nod] ],nod = T[nod]);
}
II db afis(db dist)
{
db rez = (db) dist / Dimp;
return sqrt(rez);
}
II void solve()
{
int Q0 = 0;
FOR(i,1,N)
FOR(j,1,N)
Q[++Q0] = D[i][j] = dist(Q1[i],Q2[j]);
sort(Q+1,Q+Q0+1);
int aux = Q0;
Q0 = 0;
FOR(i,1,aux)
if(i==1 || Q[i] != Q[i-1])
Q[++Q0] = Q[i];
// FOR(i,1,Q[0])
// printf("%lf\n",afis(Q[i]) );
int m,step;
for(step = 1;step <= Q0;step <<= 1);
for(m=1;step;step >>= 1)
if(m + step <= Q0 && !cuplaj(Q[m+step-1]) )
m += step;
db rez = (db)Q[m] / (db)Dimp;
printf("%lf ",sqrt(rez));
A.clear();
A.resize(1<<10);
flow(m);
rez = 0;
FOR(i,1,N)
FOR(j,1,N)
if(D[i][j] <= Q[m] && !C[i][j+N])
rez += distf(D[i][j+N]);
printf("%lf",rez);
}
int main()
{
scan();
solve();
return 0;
}