#include<stdio.h>
#include<string.h>
#include <math.h>
#include <vector>
#include <algorithm>
#define PB push_back
#define MP make_pair
#define EPS 1e-6
#define ABS(a) ( (a) < 0 ? -(a) : (a) )
#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
#define NMAX 825
#define INF 100000001
using namespace std;
vector <double> Dist;
vector <int> Adj[NMAX];
vector <double> Cost[NMAX];
struct per { double x, y; } V[NMAX];
int L[NMAX], R[NMAX], U[NMAX];
int P[NMAX];
int C[NMAX][NMAX], F[NMAX][NMAX];
int N, NN;
int i, j, Nr, FLX;
int l, r, c;
double D[NMAX];
double cost_, CST, minm;
void unite(int x, int y, double z, int capa)
{
C[x][y] = capa;
Adj[x].PB(y);
Cost[x].PB(z), Cost[y].PB(-z);
}
void unite_n(int x, int y, double z, int capa)
{
C[x][y] = capa;
Adj[x].PB(y), Adj[y].PB(x);
Cost[x].PB(z), Cost[y].PB(-z);
}
int PairUp(int x, double c_max)
{
int i;
int sz = Adj[x].size();
if (U[x]) return 0;
U[x] = 1;
for (i = 0; i < sz; i++)
if ( Cost[x][i] < c_max || ABS( Cost[x][i] - c_max) < EPS )
if ( R[Adj[x][i]] == -1 || PairUp(R[Adj[x][i]], c_max) )
{
R[L[x] = Adj[x][i]] = x;
return 1;
}
return 0;
}
int augment(double c_max)
{
memset(L, 0xFF, sizeof(L));
memset(R, 0xFF, sizeof(R));
memset(U, 0xFF, sizeof(U));
for (i = 1; i <= NN/2; i ++)
if (!PairUp(i, c_max))
{
memset(U, 0, sizeof(U));
PairUp(i, c_max);
}
int Ans = 0;
for (i = 1; i <= NN; i ++)
if (L[i] != -1) ++ Ans;
return Ans;
}
int bellford(double cst_max)
{
int changed, i, j, k;
for (i = 0; i <= NN + 1; i++) D[i] = INF, P[i] = -1;
D[0] = 0.0, changed = 1;
for (k = 1; k <= NN + 1 && changed; k++)
for (i = 0 , changed = 0; i <= NN + 1; i++)
{
int sz = Adj[i].size();
for (j = 0; j < sz; j++)
{
int nod = Adj[i][j];
double costul = Cost[i][j];
if ( ABS(costul - cst_max) < EPS || costul < cst_max)
if(C[i][nod] > F[i][nod] && D[i] + costul < D[nod])
{
D[ nod ] = D[i] + costul;
P[ nod ] = i;
changed = 1;
}
}
}
return D[NN + 1] < INF;
}
void maxflminc(double cst_max)
{
int min, cap;
while( 1 )
{
if( bellford(cst_max) )
{
min = INF;
for(i = NN + 1; P[i] >= 0; i = P[i])
{
cap = C[ P[i] ][i] - F[ P[i] ][i];
if(min > cap) min = cap;
}
for(i = NN + 1; P[i] >= 0; i = P[i])
{
F[ P[i] ][i] += min;
F[i][ P[i] ] -= min;
}
CST += min * D[NN + 1];
}
else break;
}
}
int main()
{
freopen("adapost.in", "r", stdin);
freopen("adapost.out", "w", stdout);
scanf("%d", &N);
NN = 2 * N;
for (i = 1; i <= NN; i++) scanf("%lf %lf", &V[i].x, &V[i].y);
for (i = 1; i <= N; i++)
for (j = N + 1; j <= NN; j++)
{
cost_ = sqrt( (V[j].x - V[i].x) * (V[j].x - V[i].x) + (V[j].y - V[i].y) * (V[j].y - V[i].y) );
Dist.PB(cost_);
unite_n(i, j, cost_, 1);
}
sort(Dist.begin(), Dist.end());
l = 0, r = Dist.size() - 1;
minm = INF;
while (l <= r)
{
c = (l + r) / 2;
FLX = augment(Dist[c]);
if (FLX == N) r = c - 1, minm = MIN(Dist[c], minm);
else l = c + 1;
}
//for (i = 0; i <= NN + 1; i++) Adj[i].clear(), Cost[i].clear();
memset(F, 0, sizeof(F));
for (i = 1; i <= N; i++) unite_n(0, i, 0.0, 1);
/*for (i = 1; i <= N; i++)
for (j = N + 1; j <= NN; j++)
{
cost_ = sqrt( (V[j].x - V[i].x) * (V[j].x - V[i].x) + (V[j].y - V[i].y) * (V[j].y - V[i].y) );
unite_n(i, j, cost_, 1);
}*/
for (i = N + 1; i <= NN; i++) unite_n(i, NN + 1, 0.0, 1);
maxflminc(minm);
printf("%.5lf %.5lf\n", minm, CST);
return 0;
}