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 REP(i, n, N) for(ll i=(n); i<(N); i++)
#define RREP(i, n, N) for(ll i=(N-1); i>=(n); i--)
#define LREP(lst,itr) for(auto itr = lst.begin(); itr != lst.end(); ++itr)
#define CK(n, a, b) ((a)<=(n)&&(n)<(b))
#define ALL(v) (v).begin(),(v).end()
#define MCP(a, b) memcpy(b,a,sizeof(b))
#define P(s) cout<<(s)<<endl
#define P2(a, b) cout<<(a)<<" "<<(b)<<endl
#define P3(a, b, c) cout<<(a)<<" "<<(b)<<" "<<(c)<<endl
#define V2(T) vector<vector<T>>
typedef long long ll;
using namespace std;
const ll MOD = 1e9 + 7;
const ll INF = 1e18;

int main(){
    int N;
    cin >> N;
    vector<string> field(N);
    REP(i,0,N) cin >> field[i];
    int graph[N][N];
    REP(i,0,N){
        REP(j,0,N){
            if(field[i][j]=='1'){
                graph[i][j]=1;
            }else{
                graph[i][j]=0;
            }
        }
    }

    // REP(i,0,N){
    //     REP(j,0,N){
    //         cout << graph[i][j] << " ";
    //     }
    //     cout << endl;
    // }

    int ans=0;
    REP(start,0,N){
        //幅優先探索 (グラフ: 配列)
        queue<int> q; //<コスト, ノード>
        int dist[N];
        bool visited[N];
        for(int i=0; i<N; i++) dist[i]=-1; 
        for(int i=0; i<N; i++) visited[i]=false;    //初期位置を設定
        for(int i=0; i<N; i++) dist[i] = -1;// 最後まで-1なら到達不可能
        q.push(start);  //開始ノードを追加
        dist[start] = 1; // 初期状態のコスト

        while(!q.empty()){
            int curNode = q.front();
            int curStep = dist[curNode];
            q.pop();
            //if(curStep > R) continue;    //制限ステップ数を超えたら打ち切り
            if(visited[curNode]) continue;
            visited[curNode] = true;

            for(int nextNode=0; nextNode<N; nextNode++){
                if(graph[curNode][nextNode]==0) continue;
                if(!visited[nextNode]){     //未到達のノードだけpush.
                    q.push(nextNode);
                    dist[nextNode] = curStep + graph[curNode][nextNode];
                }
            }
        }

        bool flag=true;
        REP(i,0,N){
            REP(j,0,N){
                if(graph[i][j]) if(abs(dist[i]-dist[j])!=1){
                    flag=false;
                }
            }
        }
        int maxi=0;
        if(flag){
            REP(i,0,N){
                maxi = max(maxi, dist[i]);
            }
        }
        ans = max(ans,maxi);
    }
    if(ans==0){
        P(-1);
    }else{
        P(ans);
    }
}