//{{{
#include<algorithm>
#include<cmath>
#include<deque>
#include<fstream>
#include<iomanip>
#include<iostream>
#include<map>
#include<numeric>
#include<queue>
#include<random>
#include<set>
#include<sstream>
#include<sys/time.h>
#include<unordered_map>
#include<unordered_set>
#include<vector>
using ll = long long;
enum : int { M = (int)1e9 + 7 };
enum : ll { MLL = (ll)1e18L + 9 };
using namespace std;
#ifdef LOCAL
#include"rprint2.hpp"
#else
#define FUNC(name) template <ostream& out = cout, class... T> void name(T&&...){ }
FUNC(printde) FUNC(printdbe) FUNC(printdwe) FUNC(printdu);
#endif
template <template <class T, class = std::allocator<T>> class V, class E>
istream& operator >> (istream& in, V<E>& v){ for(auto& e : v){ in >> e; } return in; }
//}}}

struct Graph{
    struct Node{
        vector<int> dests;
        int color = -1;
    };
    vector<Node> nodes;
    Graph(int num): nodes(num){ }
    int id(Node* n){ return n - &nodes[0]; }
    int id(Node& n){ return &n - &nodes[0]; }
    // void print(){ for(auto& node : nodes){ prints(id(node), node.dests); } }
    void add1Edge(int from, int dest){
        nodes[from].dests.push_back(dest);
    }
    void add2Edge2(int from, int dest){
        add1Edge(from, dest);
        add1Edge(dest, from);
    }
    bool isBipartile(int idx, int color = 0, int from = -1){
        if(nodes[idx].color == -1){
            nodes[idx].color = color;
        }else{
            return nodes[idx].color == color;
        }
        for(int didx : nodes[idx].dests){
            if(didx == from){ continue; }
            if(!isBipartile(didx, !color, idx)){
                return false;
            }
        }
        return true;
    }
    ll dijkstra(int start, int goal){
        struct DElem{
            int cost, dest;
            bool operator < (const DElem& e) const { return cost > e.cost; }
        };
        priority_queue<DElem> pq;
        // vector<int> visited(nodes.size());
        static vector<int> visited;
        visited.assign(nodes.size(), 0);
        pq.push({0, start});
        while(pq.size()){
            auto e = pq.top(); pq.pop();
            if(visited[e.dest]){ continue; }
            visited[e.dest] = true;
            if(e.dest == goal){
                return e.cost;
            }
            // for(auto& edge : nodes[e.dest].edges){
            //     pq.push({e.cost + edge.cost, edge.dest});
            // }
            for(int didx : nodes[e.dest].dests){
                pq.push({e.cost + 1, didx});
            }
        }
        return -1;
    }
};

int main(){
    cin.tie(0); ios::sync_with_stdio(false);
    int n; cin >> n;
    // vector<vector<int>> ss(n, vector<int>(n)); cin >> ss;
    Graph g(n);
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            char s; cin >> s;
            if(s == '1' && i < j){
                g.add2Edge2(i, j);
            }
        }
    }
    if(!g.isBipartile(0)){
        cout << -1 << '\n';
        return 0;
    }
    int ans = 0;
    for(int i = 0; i < n; i++){
        for(int j = i + 1; j < n; j++){
            int len = g.dijkstra(i, j);
            ans = max(ans, len);
        }
    }
    cout << ans + 1 << '\n';
}


Measured memory_bytes: 888