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

#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define MIN(a) *min_element(all(a))
#define MAX(a) *max_element(all(a))
#define SUM(a) accumulate(all(a), 0LL)
#define REP(i, n) for(int (i)=0; (i)<(n); (i)++)
#define RREP(i, n) for(int (i)=(n)-1; (i)>=0; (i)--)
#define FOR(i, m, n) for(int (i)=(m); (i)<(n); i++)
#define FORR(i, m, n) for(int (i)=(n)-1; (i)>=(m); i--)
#define debug(x) cerr << #x << " = " << x << endl
//#define int long long

typedef long long ll;
//ll const MOD = 998244353;
ll const MOD = 1e9+7;
int const inf = 1e9;
ll const INF = 1e18;

inline void ios_(){cin.tie(0); ios::sync_with_stdio(false);}
template<typename T> int size(const T& a){return (int)a.size();}
template<typename T> T Div(T a, T b){return (a + b - 1) / b;}
template<typename T> bool chmin(T& a, const T& b){if(a > b){a = b; return true;} return false;}
template<typename T> bool chmax(T& a, const T& b){if(a < b){a = b; return true;} return false;}

//Graph in adjcency list
struct Graph{
    struct Edge{
        int from;
        int to;
        ll cost;
        Edge(int a, ll b) : to(a), cost(b) {}
        Edge(int a, int b, ll c) : from(a), to(b), cost(c) {}
    };

    int N;  //頂点数
    vector<vector<Edge>> edges;   //隣接リスト
    vector<ll> dist;   //ノードの深さ
    ll diam;            //木の直径
    vector<int> deg;    //入次数
    vector<int> cycle;  //サイクル

    Graph(int n) : N(n), edges(n), dist(n, INF), diam(INF), deg(n, 0){}

    void connect(int a, int b, ll c){   //辺を追加
        edges[a].emplace_back(Edge(a, b, c));
        deg[b]++;
    }

    bool visited(int v){
        return dist[v] < INF;
    }

    void resetDist(){
        for(int i=0; i<N; i++){
            dist[i] = INF;
        }
    }
};

struct MatrixGraph : Graph {
    MatrixGraph(int n) : Graph(n) {
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                edges[i].emplace_back(Edge(i, j, (i == j ? 0 : INF)));
            }
        }
    }

    void connect(int a, int b, ll c) {
        edges[a][b].cost = c;
    }

    int bfs(int start) {
        queue<Edge> que;
        vector<vector<bool>> eflag(N, vector<bool>(N, false));

        for(const auto& e : edges[start]) {
            if(e.cost < INF) {
                que.push(e);
                eflag[start][e.to] = true;
                eflag[e.to][start] = true;
            }
        }

        while(!que.empty()) {
            Edge edge = que.front();
            que.pop();

            int v = edge.to;
            ll d = edge.cost;

            if(dist[v] == INF) {
                dist[v] = d;
            } else if(dist[v] == d) {
                continue;
            } else {
                return -1;
            }

            for(const auto& e : edges[v]) {
                if(e.cost < INF && !eflag[v][e.to]) {
                    que.push(Edge(v, e.to, d + e.cost));
                    eflag[v][e.to] = true;
                    eflag[e.to][v] = true;
                }
            }
        }

        return MAX(dist) + 1;
    }

    void WarshallFloyd() {
        for(int k = 0; k < N; k++) {
            for(int i = 0; i < N; i++) {
                for(int j = 0; j < N; j++) {
                    ll d = edges[i][k].cost + edges[k][j].cost;
                    if(d < edges[i][j].cost) {
                        edges[i][j].cost = d;
                    }
                }
            }
        }
    }
};

signed main(){
    int n;
    cin >> n;

    MatrixGraph G(n);
    REP(i, n){
        REP(j, n){
            char c;
            cin >> c;
            if(c == '1'){
                G.connect(i, j, 1);
            }
        }
    }

    int ans = -1;
    REP(i, n){
        G.resetDist();
        chmax(ans, G.bfs(i));
    }

    cout << ans << endl;

    return 0;
}


Measured memory_bytes: 1520