#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl "\n"
#define REP(i,a,n) for(int i=a;i<n;++i)
#define REPR(i,a,n) for(int i=a;i>n;--i)
#define RUP(a,b) ((a+b-1)/(b))
#define ALL(v) (v).begin(),(v).end()
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define MOD 1000000007
#define INF LLONG_MAX/2

typedef long long ll;
typedef pair<int,int> Pii;
typedef tuple<int,int,int> Tiii;
typedef vector<int> Vi;
typedef vector<Vi> VVi;
typedef vector<Pii> VPii;
typedef vector<string> Vs;

template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
template<class T> void YesNo(T a) {cout<<(a?"Yes":"No")<<endl;}
template<class T> void YESNO(T a) {cout<<(a?"YES":"NO")<<endl;}
void vin(Vi &v){REP(i,0,(v).size()) cin>>v[i];}
void vin(Vi &v,Vi &v2){REP(i,0,(v).size()) cin>>v[i]>>v2[i];}
void vout(Vi &v){for(int i=0;i<(v).size();i++) cout<<v[i]<<" ";cout<<endl;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
void uniq(Vi &v){sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end());}
int ctoi(char c){if(c>='0'&&c<='9'){return c-'0';}return 0;}
void accum(Vi &v){REP(i,1,(v).size()) v[i]+=v[i-1];}
bool comp(Pii a,Pii b){
    if(a.second != b.second) return a.second<b.second;
    else return a.first<b.first;
}

bool flag=true;

void bfs(int n, int start , vector<VPii> connect){
    Vi dist(n,INF);
    queue<Pii> q;
    q.push(mp(start,0));
    while(!q.empty()){
        int now,depth;
        tie(now,depth)=q.front();
        q.pop();
        if(depth>=dist[now]) continue;
        dist[now]=depth;
        REP(i,0,connect[now].size()){
            int next=connect[now][i].first;
            if(dist[next]!=INF && (dist[next]-depth)%2==0){cout<<-1<<endl;flag=false;return;}
            if(dist[next]==INF) q.push(mp(next,depth+1));
        }
    }
}

void solve(long long n, std::vector<string> s){
    vector<vector<Pii>> connect(n);
    REP(i,0,n){
        REP(j,0,n){
            if(s[i][j]=='1'){
                connect[i].pb(mp(j,1));
                connect[j].pb(mp(i,1));
            }
        }
    }
    bfs(n,0,connect);
    if(flag==false) return;

    vector<vector<int>> dist(n,Vi(n,INF));
    REP(i,0,n) dist[i][i]=0;
    REP(i,0,n){
        REP(j,0,n){
            if(s[i][j]=='1'){
                dist[i][j]=1;
                dist[j][i]=1;    
            }
        }
    }

     REP(i,0,n){
         REP(j,0,n){
             REP(k,0,n){
                 chmin(dist[j][k],dist[j][i]+dist[i][k]);
             }
         }
     }

     int ans=-1;
     REP(i,0,n){
         REP(j,0,n){
             chmax(ans,dist[i][j]);
//            cout<<dist[i][j]<<" ";
         }
//         cout<<endl;
     }
     cout<<ans+1<<endl;


    // Vi dist(n,INF);
    // bfs(dist,0,connect);
    // if(!flag) return;
    // // priority_queue<Tiii,vector<Tiii>,greater<Tiii>> q;
    // // q.push(make_tuple(0,0,-1));
    // // while(!q.empty()){
    // //     int nowdist,now,past;
    // //     tie(nowdist,now,past)=q.top();
    // //     q.pop();
    // //     if(nowdist>dist[now]) continue;
    // //     dist[now]=nowdist;
    // //     REP(i,0,connect[now].size()){
    // //         int next=connect[now][i].first,cost=connect[now][i].second;
    // //         if(next!=past && dist[next]!=INF && (nowdist+cost-dist[next])%2==1){cout<<-1<<endl;return;}
    // //         if(next!=past && nowdist+cost<dist[next]){
    // //             q.push(make_tuple(nowdist+cost,next,now));
    // //             dist[next]=nowdist+cost;
    // //         }
    // //     }
    // // }
    // int tmps=-1,maxd=-1;
    // REP(i,0,n){
    //     if(dist[i]>maxd){
    //         tmps=i;
    //         maxd=dist[i];
    //     }
    // }

    // // priority_queue<Tiii,vector<Tiii>,greater<Tiii>> q2;
    // // Vi dist2(n,INF);
    // // dist2[tmps]=0;
    // // q2.push(make_tuple(0,tmps,-1));
    // // while(!q2.empty()){
    // //     int nowdist,now,past;
    // //     tie(nowdist,now,past)=q2.top();
    // //     q2.pop();
    // //     if(nowdist>dist2[now]) continue;
    // //     dist2[now]=nowdist;
    // //     REP(i,0,connect[now].size()){
    // //         int next=connect[now][i].first,cost=connect[now][i].second;
    // //         if(next!=past && dist2[next]!=INF && (nowdist+cost-dist2[next])%2==1){cout<<-1<<endl;return;}
    // //         if(next!=past && nowdist+cost<dist2[next]){
    // //             q2.push(make_tuple(nowdist+cost,next,now));
    // //             dist2[next]=nowdist+cost;
    // //         }
    // //     }
    // // }

    // Vi dist2(n,INF);
    // bfs(dist2,tmps,connect);
    
    // tmps=-1;
    // maxd=-1;
    // REP(i,0,n){
    //     if(dist2[i]>maxd){
    //         tmps=i;
    //         maxd=dist2[i];
    //     }
    // }

    
    // cout<<maxd+1<<endl;
}

// Generated by 1.1.5 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
signed main(){
    long long N;
    scanf("%lld",&N);
    std::vector<string> S(N);
    for(int i = 0 ; i < N ; i++){
        cin>>S[i];
    }
    solve(N, std::move(S));
owari:
    return 0;
}


Measured memory_bytes: 3200