#include<bits/stdc++.h>
using namespace std;
#define pb          push_back
#define m_p			make_pair
#define rep(i,a,b)	for(int i=a;i<b;i++)
#define sz(x)       (int)x.size()
#define f			first
#define debug		cout<<"##########3"<<endl
#define mod			1000000007
#define ll			long long int
#define lMax		LLONG_MAX
// queue<int> , prefix_sum(a,a+n) , reverse(a,a+n) , priority_queue <int> max heap , priority_queue <int, vector<int>, greater<int> > min heap;
// == precedence gretaer then &
ll n,m;
//10:14
//10:30
//Confi++
string s[205],s1;
vector<ll> vec[10005];
ll arr[200005],vis[200005];
vector<pair<int,int> > store[200005];
priority_queue <ll> pq;
map<ll,ll> mp;
set<ll> st;
int f=0;
int G[206][206];
ll dist[206];
bool containsOdd(int src) 
{ 
    // Create a color array to store colors assigned  
    // to all veritces. Vertex number is used as index  
    // in this array. The value '-1' of  colorArr[i]  
    // is used to indicate that no color is assigned to 
    // vertex 'i'.  The value 1 is used to indicate first  
    // color is assigned and value 0 indicates second  
    // color is assigned. 
    int V = 205;
    int colorArr[V]; 
    for (int i = 0; i < V; ++i) 
        colorArr[i] = -1; 
   
    // Assign first color to source 
    colorArr[src] = 1; 
   
    // Create a queue (FIFO) of vertex numbers and  
    // enqueue source vertex for BFS traversal 
    queue <int> q; 
    q.push(src); 
   
    // Run while there are vertices in queue (Similar to BFS) 
    while (!q.empty()) 
    { 
        // Dequeue a vertex from queue  
        int u = q.front(); 
        q.pop(); 
   
        // Return true if there is a self-loop  
        if (G[u][u] == 1) 
           return true;   
   
        // Find all non-colored adjacent vertices 
        for (int v = 0; v < V; ++v) 
        { 
            // An edge from u to v exists and destination 
            // v is not colored 
            if (G[u][v] && colorArr[v] == -1) 
            { 
                // Assign alternate color to this adjacent 
                // v of u 
                colorArr[v] = 1 - colorArr[u]; 
                q.push(v); 
            } 
   
            // An edge from u to v exists and destination 
            // v is colored with same color as u 
            else if (G[u][v] && colorArr[v] == colorArr[u]) 
                return true; 
        } 
    } 
   
    // If we reach here, then all adjacent  
    // vertices can be colored with alternate 
    // color 
    return false; 
} 

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
	cout.tie(NULL);
	char a,b;
    ll i,j,k,c=0,t,z=0,x=0,y=0,cnt=0;
    
   	cin>>n;
   	
   	rep(i,0,n){
   		cin>>s[i];
	}
   	
   	for(i=0;i<n;i++){
   		for(j=0;j<n;j++){
   			G[i][j] = s[i][j]-'0';
   			if(s[i][j]=='1'){
   				vec[i+1].pb(j+1);	
			}
		}	
	}
	if(containsOdd(0)){
		cout<<-1;
		return 0;
	}
	else{
		//bfs
		for(i=1;i<=n;i++){
			
			for(j=1;j<=n;j++)
			{
				dist[j] = (1e6);
			}
			queue<ll> q;
			q.push(i);
			dist[i] = 0;
			while(!q.empty()){
				x = q.front();
				q.pop();
				
				for(auto it:vec[x]){
					if(dist[it]>dist[x]+1){
						dist[it] = dist[x] + 1;
						q.push(it);
					}
				}
				
			}
			ll maxi  = 0;
			for(j=1;j<=n;j++)
			{
				if(dist[j]!=1e6){
					maxi = max(maxi,dist[j]);
				}
			}
			cnt = max(maxi,cnt);
		}
	}
	cout<<cnt+1;
   	
 	return 0;
}

Measured memory_bytes: 8960