/*这道题不使用堆排序,直接枚举所有边权求最小边权要更快,可以节省100ms,原因是每一次堆排中,堆的初始数据都发生了变化,需要反复的建堆,如果是对少量边排序,应该是kruskal+堆排序要快*/
#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
const long M=10000000;
double dist[1001][1001],cost[1001][1001],rate[1001];
int used[1001],pre[1001],a[1001];
long n,m;
double prim(double r);
int sort();
void heap(int i);
int main()
{
double ra,rn,tmp;
long i,j;
long x[1001],y[1001],h[1001];
while (cin>>n&&n)
{
for (i=1;i<=n;i++)
cin>>x[i]>>y[i]>>h[i];
for (i=1;i<=n;i++)
for (j=i+1;j<=n;j++)
{
tmp=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]);
dist[i][j]=dist[j][i]=sqrt(tmp);
cost[i][j]=cost[j][i]=labs(h[i]-h[j]);
}
for (ra=0,rn=1;fabs(rn-ra)>=0.0001;ra=prim(ra))
rn=ra;
printf("%.3lf/n",rn);
}
return 0;
}
int sort()
{
int i;
for(m=0,i=1;i<=n;i++)
if (!used[i])
a[++m]=i;
for (i=m/2;i>=1;i--)
heap(i);
return a[1];
}
void heap(int i)
{
int j;
int tmp=a[i];
j=2*i;
while (j<=m)
{
if (j<m&&rate[a[j]]>rate[a[j+1]])
j++;
if (rate[tmp]>rate[a[j]])
{
a[i]=a[j];
i=j;
j=2*i;
}
else
break;
}
a[i]=tmp;
}
double prim(double r)
{
int i,k,t;
double sumd,sumc;
for (i=0;i<=n;i++)
{
rate[i]=M;
pre[i]=1;
used[i]=0;
}
rate[1]=0;
sumd=sumc=0;
for (k=1;k<=n;k++)
{
t=sort();
used[t]=1;
sumd+=dist[t][pre[t]];
sumc+=cost[t][pre[t]];
for (i=1;i<=n;i++)
if (!used[i]&&cost[t][i]-r*dist[t][i]<rate[i])
{
pre[i]=t;
rate[i]=cost[t][i]-r*dist[t][i];
}
}
return sumc/sumd;
}