Problem:
Score : 500 points

Problem Statement

Given is a connected undirected graph with N vertices and M edges. The vertices are numbered 1 to N, and the edges are described by a grid of characters S.
If S_{i,j} is 1, there is an edge connecting Vertex i and j; otherwise, there is no such edge.

Determine whether it is possible to divide the vertices into non-empty sets V_1, \dots, V_k such that the following condition is satisfied. If the answer is yes, find the maximum possible number of sets, k, in such a division.

Every edge connects two vertices belonging to two "adjacent" sets. More formally, for every edge (i,j), there exists 1\leq t\leq k-1 such that i\in V_t,j\in V_{t+1} or i\in V_{t+1},j\in V_t holds.

Constraints

2 \leq N \leq 200

S_{i,j} is 0 or 1.

S_{i,i} is 0.

S_{i,j}=S_{j,i}

The given graph is connected.

N is an integer.

Input

Input is given from Standard Input in the following format:

N
S_{1,1}...S_{1,N}
:
S_{N,1}...S_{N,N}

Output

If it is impossible to divide the vertices into sets so that the condition is satisfied, print -1.
Otherwise, print the maximum possible number of sets, k, in a division that satisfies the condition.

Sample Input 1

2
01
10

Sample Output 1

2

We can put Vertex 1 in V_1 and Vertex 2 in V_2.

Sample Input 2

3
011
101
110

Sample Output 2

-1

Sample Input 3

6
010110
101001
010100
101000
100000
010000

Sample Output 3

4

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
#define R register
#define mp make_pair
#define ll long long
#define pii pair<int, int>
using namespace std;
const int N = 210, inf = 1e9;

int n, g[N][N], col[N], ans, f[N][N];
char s[N];
queue<int> que;

template <class T>
inline void read(T &x) {
    x = 0;
    char ch = getchar(), w = 0;
    while (!isdigit(ch)) w = (ch == '-'), ch = getchar();
    while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    x = w ? -x : x;
    return;
}

bool dfs1(int now) {
    for (R int i = 1; i <= n; ++i) {
        if (!g[now][i]) continue;
        if (col[i]) {
            if (col[i] == col[now]) return 0;
            continue;
        }
        col[i] = col[now] ^ 1;
        if (!dfs1(i)) return 0;
    }
    return 1;
}

int main() {
    read(n);
    for (R int i = 1; i <= n; ++i) {
        scanf("%s", s + 1);
        for (R int j = 1; j <= n; ++j)
            g[i][j] = s[j] - '0';
    }
    if ((col[1] = 2) && !dfs1(1)) return printf("-1\n"), 0;
    
    for (R int i = 1; i <= n; ++i) {
        memset(col, 0, sizeof (col));
        while (que.size()) que.pop();
        que.push(i), col[i] = 1;
        while (que.size()) {
            int now = que.front();
            que.pop(), ans = max(ans, col[now]);
            for (R int j = 1; j <= n; ++j) {
                if (!g[now][j] || col[j]) continue;
                col[j] = col[now] + 1, que.push(j);
            }
        }
    }/*
    for (R int i = 1; i <= n; ++i) {
        for (R int j = 1; j <= n; ++j)
            f[i][j] = g[i][j] ? 1 : inf;
        f[i][i] = 0;
    }
    for (R int i = 1; i <= n; ++i)
        for (R int j = 1; j <= n; ++j)
            for (R int k = 1; k <= n; ++k)
                f[j][k] = min(f[j][i] + f[i][k], f[j][k]);
    for (R int i = 1; i <= n; ++i)
        for (R int j = 1; j <= n; ++j)
            if (f[i][j] != inf) ans = max(ans, f[i][j]);*/
    cout << ans << endl;
    return 0;
}