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)

//
// Created by HandwerSTD.
// Copyright (c) 2019 HandwerSTD. All rights reserved.
// Title: Graph Partition
//
// sto Qingyu orz
// 感谢真神sqy无私的教诲。膜时队者处处阿克，只因大师sqy在他背后。不膜大师者违背了真神的旨意，真神必将降下天谴，
// 使其天天爆零
// 我不由自主地膜拜真神sqy。
//

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>

#define FILE_IN(__fname) freopen(__fname, "r", stdin)
#define FILE_OUT(__fname) freopen(__fname, "w", stdout)
#define rap(a,s,t,i) for (int a = s; a <= t; a += i)
#define down(a,t,s,i) for (int a = t; a >= s; a -= i)
#define IMPROVE_IO() std::ios::sync_with_stdio(false)

using std::cin;
using std::cout;
using std::endl;

typedef long long int lli;

int getint() { int x; scanf("%d", &x); return x; }
lli getll() { long long int x; scanf("%lld", &x); return x; }

const int MAXN = 200 + 10;
const int dx[] = { 0, 1, -1, 0, 0 };
const int dy[] = { 0, 0, 0, 1, -1 };

int n, G[MAXN][MAXN];
char s[MAXN];
short col[MAXN];

bool biColor(int now, bool color) {
    std::queue<int> q;
    q.push(now); col[now] = color;
    while (!q.empty()) {
        int u = q.front(); q.pop();
        for (int i = 1; i <= n; ++i) {
            if (G[u][i] == 0x3f3f3f3f || i == u) continue;
            int v = i;
            if (col[v] == -1) { col[v] = !col[u]; q.push(v); }
            else if (col[v] == col[u]) return false;
        }
    }
    return true;
}

int main() {
    n = getint();
    memset(G, 0x3f, sizeof G);
    memset(col, -1, sizeof col);
    for (int i = 1; i <= n; ++i) {
        scanf("%s", s);
        for (int j = 1; j <= n; ++j) {
            if (s[j - 1] == '1') G[i][j] = 1;
        }
        G[i][i] = 0;
    }
    if (!biColor(1, 0)) return (0 & printf("-1\n"));
    for (int k = 1; k <= n; ++k) {
        for (int i = 1; i <= n; ++i) {
            for (int j = 1; j <= n; ++j) {
                G[i][j] = std::min(G[i][j], G[i][k] + G[k][j]);
            }
        }
    }
    int maxDis = 0;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= n; ++j) {
            if (G[i][j] != 0x3f3f3f3f && G[i][j] > maxDis) maxDis = G[i][j];
        }
    }
    printf("%d\n", maxDis + 1);
    return 0;
}