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: Wrong Answer)

#include <bits/stdc++.h>
using namespace std;
#define ll int
#define REP(i,n) for(int i=0;i<n;++i)
#define REPP(i,m,n) for(int i=m;i<n;++i)
#define rep(i,n) for(int i = n-1;i>=0;--i)
#define repp(i,n,m) for(int i = n-1; i >= m; --i)
#define ALL(N) (N.begin(),N.end())
#define de cout << "line : " << __LINE__ << " debug" << endl;
#define pb push_back
#define pq priority_queue
#define Dcout(N) cout << setprecision(20) << N << endl
constexpr int INF = 2047483647;
int N;
char S[210][210];
vector<int> G[210];
bool flag = 0;
bool used[210];
int minv[210] = {};
bool USED[210][210];
int tmp,tmo;

void dfs(int X,int sta,int end){
    REP(i,G[X].size()){
        if(G[X][i] == end && X == sta) continue;
        else if(G[X][i] == end){flag = 1;tmp = sta;tmo = end;return;}
        if(used[G[X][i]]) continue;
        else used[G[X][i]] = 1;
        used[end] = 0;
        dfs(G[X][i],sta,end);
    }
}

void DFS(int X,int end){
    REP(i,G[X].size()){
        if(USED[X][G[X][i]]) continue;
        USED[X][G[X][i]] = 1;
        minv[G[X][i]] = min(minv[X]+1,minv[G[X][i]]);
        DFS(G[X][i],end);
    }
}

signed main() {
    cin.tie(0);
	ios::sync_with_stdio(false);
    cin >> N;
    REP(i,N){
        REP(j,N){
            cin >> S[i][j];
          if(i > j) continue;
            if(S[i][j] == '1'){
                G[i].pb(j);
                G[j].pb(i);
            }
        }
    }
    if(N > 2) REP(i,N){
        REP(j,210){used[i] = 0;}
        REP(j,G[i].size()){
            dfs(G[i][j],G[i][j],i);
        }
        dfs(i,i,i);
        if(flag){
          REP(k,N){minv[k] = INF;}
          minv[tmp] = 0;
            DFS(tmp,tmo);
            if(minv[tmo] % 2 == 1){
                cout << -1 << endl;
                return 0;
            }
        }
    }
    int ans = 0;
    REP(i,N){
        REPP(j,i+1,N){
            if(i == j)continue;
            if(G[i].size() == 1 && G[j].size() == 1){
                REP(k,N)REP(l,N){
                    USED[k][l] = 0;
                }
                REP(k,N){minv[k] = INF;}
                minv[i] = 0;
                DFS(i,j);
                ans = max(ans,minv[j]);
            }
        }
    }
    cout << ans+1 << endl;
}