#include<bits/stdc++.h>
using namespace std;
inline int read();
inline void write(int x);
struct node{
int xx,yy;
}a[155];
int n;
double xlen,ylen;//xx是第一个牧场的直径,yy是第二个的
double maxlen;//连接后的直径
int id1,id2;
double minn=2e9;//最好的连接方式
//数组名字不要搞混了
bool d[155][155];//i,j联通?1为是,0为否
double dis[155][155];//i,j的距离
bool in[155];//i牧场属于哪个大牧场,同时在染色中防止走重复
double calc(int x,int y);//求距离
inline void floyd();
void dfs(int x){
in[x]=1;
for(int i=1;i<=n;i++){
if(d[x][i]==1 && in[i]==0){
dfs(i);
}
}
}
void get(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(d[i][j]==0) continue;
if(i==j) continue;
if(in[i]) xlen=max(xlen,dis[i][j]);
else ylen=max(ylen,dis[i][j]);
}
}
}
void get2(){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(in[i]+in[j]==1){
if(minn>calc(i,j)){
minn=calc(i,j),id1=i,id2=j;
}
}
}
}
}
int main(){
n=read();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) dis[i][j]=2e9;
for(int i=1;i<=n;i++){
a[i].xx=read();
a[i].yy=read();
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
char ch;cin>>ch;
d[i][j]=d[j][i]=ch-'0';
if(d[i][j]) dis[i][j]=dis[j][i]=calc(i,j);
}
}
//读入无问题
//染色得到两个大牧场(无问题)
dfs(1);
//floyd求距离(ok)
floyd();
//分别得到直径——xlen为第一个的,ylen为第二个的(完成)
get();
//获得最好的连接方式
get2();
//将其连接,求出新的直径
d[id1][id2]=d[id2][id1]=1;
dis[id1][id2]=dis[id2][id1]=minn;
floyd();
//输出
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(d[i][j]) maxlen=max(maxlen,dis[i][j]);
}
printf("%.6lf",max(min(xlen,ylen),maxlen));
return 0;
}
inline int read(){
int s=0,f=1;char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f*=-1;
ch=getchar();
}
while(isdigit(ch))
s=s*10+ch-'0',ch=getchar();
return s*f;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
double calc(int x,int y){
return sqrt(((a[x].xx-a[y].xx)*(a[x].xx-a[y].xx))+((a[x].yy-a[y].yy)*(a[x].yy-a[y].yy)));
}
inline void floyd(){
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(k==i || i==j || k==j) continue;
if(dis[i][k]+dis[j][k]<dis[i][j]){
dis[i][j]=dis[i][k]+dis[j][k];
d[i][j]=d[i][k]=d[j][k]=1;
}
}
}
}
}