#include <algorithm>
#include <iostream>
#include <iomanip>
#include <numeric>
#include <vector>
#include <string>
#include <bitset>
#include <stack>
#include <queue>
#include <tuple>
#include <regex>
#include <cmath>
#include <map>
#include <set>
#include <functional>
#include <cstring>

using namespace std;

template<typename T> bool chmax( T &a, const T b ) { if ( a <= b ) { a = b; return ( true ); } else { return ( false ); } }
template<typename T> bool chmin( T &a, const T b ) { if ( a >= b ) { a = b; return ( true ); } else { return ( false ); } }

using ll = long long;
using Pint = pair<int, int>;
using Pll  = pair<ll, ll>;

#define eb emplace_back
#define pb push_back
#define mp make_pair

#define F first
#define S second

#define popcnt __builtin_popcountll

#define rep( i, n ) for ( ll i = 0; i < (ll)( n ); ++i )
#define reps( i, n ) for ( ll i = 1; i <= (ll)( n ); ++i )
#define rrep( i, n ) for ( ll i = (ll)( ( n ) - 1 ); i >= 0; --i )
#define rreps( i, n ) for ( ll i = (ll)( ( n ) ); i > 0; --i )
#define arep( i, v ) for ( auto &&i : ( v ) )

#define ALL( c ) ( c ).begin(), ( c ).end()
#define RALL( c ) ( c ).rbegin(), ( c ).rend()
#define UNIQUE( c ) ( c ).erase( unique( ( c ).begin(), ( c ).end() ), ( c ).end() )

template<typename T = ll> constexpr T MAX = numeric_limits<T>::max();
template<typename T> T gcd( const T a, const T b ) { return ( b ? gcd( b, a % b ) : a ); }
template<typename T> T lcm( const T a, const T b ) { return ( a / gcd( a, b ) * b ); }

template<typename T> struct BiPartiteGraph {
	using P = pair<T, T>;
	BiPartiteGraph( T n ) {
		g.assign( n, vector<T>( n, 0 ) );
		init( n );
	}
	BiPartiteGraph( const vector<vector<T>> &val, T n ) {
		g = val;
		init( n );
	};

	void init( T n ) {
		size = n;
		dir.assign( n, 0 );
	}

	bool dfs( T v, T vdir, P &num ) {
		bool res = true;
		dir[v] = vdir;
		if ( vdir == 1 ) ++num.F;
		else if ( vdir == -1 ) ++num.S;
		arep( it, g[v] )
		{
			if ( dir[it] == 0 )
			{
				if ( dfs( it, -vdir, num ) == false )
					res = false;
			}
			else if ( dir[it] != -vdir ) res = false;
		}

		return ( res );
	}

	bool check() {
		bool res = true;
		rep( v, size )
		{
			if ( dir[v] != 0 ) continue;
			P num = { 0, 0 };
			if ( dfs( v, 1, num ) == false )
				res = false;
			nums.pb( num );
		}

		return ( res );
	}

	T size;
	vector<vector<T>> g;
	vector<T> dir;
	vector<P> nums;
};


int main()
{
	ll n; cin >> n;
	constexpr ll inf = 1e18;
	vector<string> ss( n );
	vector<vector<ll>> g( n );
	rep( i, n )
	{
		cin >> ss[i];
		rep( j, ss[i].size() )
			if ( ss[i][j] == '1' )
				if ( i != j )
				{
					g[i].eb( j );
					g[j].eb( i );
				}
	}

	BiPartiteGraph<ll> bg( g, n );
	if ( bg.check() == false )
	{
		cout << -1 << endl;
		return ( 0 );
	}

	vector<vector<ll>> cost( n, vector<ll>( n, inf ) );
	rep( i, n )
	{
		rep( j, n )
		{
			if ( i == j )
				cost[i][j] = 0;
			else if ( ss[i][j] == '1' )
				cost[i][j] = cost[j][i] = 1;
		}
	}

	rep( k, n )
		rep( i, n )
			rep( j, n )
				chmin( cost[i][j], cost[i][k] + cost[k][j] );

	ll ans = 0;
	rep( i, n ) rep( j, n ) if ( cost[i][j] < inf ) chmax( ans, cost[i][j] );
	cout << ans + 1 << endl;

	return ( 0 );
}


Measured memory_bytes: 4620