#include <iostream>
#include <iomanip>
#include <random>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <numeric>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <sstream>
#include <bitset>
#include <cassert>
#include <fstream>
#include <queue>
#include <stack>
#include <unordered_map>

#define len(X) ((int)(X).size())

#ifdef __LOCAL
#define DBG(X) cout << #X << "=" << (X) << '\n';
#define SAY(X) cout << (X) << '\n';
#else
#define DBG(X)
#define SAY(X)
#endif

#define M_PI       3.14159265358979323846

using namespace std;

using ll = long long int;
using ull = unsigned long long int;
using ld = long double;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

const int INT_INF = (int)(2e9);
const ll  LL_INF = (ll)(2e18);

const int NIL = -1;
static mt19937 _g(time(nullptr));

inline ll randint(ll a, ll b) { ll w = (_g() << 31LL) ^ _g(); return a + w % (b - a + 1); }
inline void fast_io() { ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); };
template<typename T> inline T sign(T x) { return T(x > 0) - T(x < 0); }
template<typename T, typename S> inline ostream& operator<<(ostream& os, const pair<T, S> p) { cout << "[" << p.first << ";" << p.second << "]"; return os; }
template<typename T> inline ostream& operator<<(ostream& os, const vector<T>& v) { for (auto el : v) cout << el << " "; return os; }
template<typename T> inline T fetch() { T ret; cin >> ret; return ret; }
template<typename T> inline vector<T> fetch_vec(int sz) { vector<T> ret(sz); for (auto& elem : ret) cin >> elem; return ret; }

bool isBipartite(int N, vector<vector<int>>& adjs)
{
    vector<int> colors(N, 0);

    queue<int> q;
    q.push(0);
    colors[0] = 1;

    while (!q.empty())
    {
        int n = q.front();
        q.pop();

        for (auto& adj : adjs[n])
        {
            if (n == adj) // self loop
                return false;

            if (colors[adj] != 0 && colors[adj] == colors[n])
                return false;

            if (colors[adj] == 0)
            {
                colors[adj] = -colors[n];
                q.push(adj);
            }
        }
    }

    return true;
}

int maxShortestPath(int N, vector<vector<int>>& adjs)
{
    const int NC = 201;
    vector<vector<int>> dp(N, vector<int>(N, NC));

    for (int n = 0; n < N; ++n)
    {
        for (auto& adj : adjs[n])
            dp[n][adj] = 1;
    }

    for (int k = 0; k < N; ++k)
    {
        for (int i = 0; i < N; ++i)
        {
            if (i == k) continue;

            for (int j = 0; j < N; ++j)
            {
                if (i == j || j == k) continue;

                if (dp[i][k] != NC && dp[k][j] != NC &&
                    dp[i][j] > dp[i][k] + dp[k][j])
                {
                    dp[i][j] = dp[i][k] + dp[k][j];
                }
            }
        }
    }

    int maxPath = 0;

    for (int i = 0; i < N; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            if (dp[i][j] != NC)
                maxPath = std::max(maxPath, dp[i][j]);
        }
    }

    return maxPath;
}

int solve()
{
    int N;
    std::cin >> N;
    char c = 0;

    vector<vector<int>> adjs(N, vector<int>());

    int counter = 0;

    for (int row = 0; row < N; ++row)
    {
        for (int col = 0; col < N; ++col)
        {
            std::cin >> c;
            if (c == '1')
                adjs[row].push_back(col);
        }
    }

    int ans = -1;

    if (isBipartite(N, adjs))
        ans = maxShortestPath(N, adjs) + 1;

    return ans;
}

int main() {
    fast_io();

    int i = solve();

    std::cout << i << std::endl;

    return 0;
}


Measured memory_bytes: 512