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>

using namespace std;
inline void prep ()
{
  cin.tie (0);
  cin.sync_with_stdio (0);
};
const double pi = acos(-1.);
//printf(%.12lf\n,mid);
// __builtin_popcount(int) count 1's in binary
// get decimal part of number
/*
double intpart;
double thiss = modf((double)(n*m)/(double)k, &intpart);
*/
// round = (int)(num+.5)
int mod = 998244353;

long long mymod(long long num){
  if (num< 0 && !(num%mod == 0)){
    if (mod == 1){
      return 0;
    }
    return mod-abs(num)%mod;
  }else{
    return num%mod;
  }
}

/*string sentence = And I feel fine...;
    istringstream iss(sentence);
*/  

double eps = .000000001;
vector<int> graph[201];
bool vis[201];

int vals[201];
bool good = true;
void bip(int node, int val){
    if (vis[node] || !good){
        return;
    }
    vis[node] = true;
    vals[node] = val;
    for (int i=0; i<graph[node].size(); i++){
        int cur = graph[node][i];
        if (vals[cur] == val){
            good = false;
            break;
        }
        int newval = 1;
        if (val == 1){
            newval = 2;
        }
        bip(cur, newval);
    }
}
int main ()
{
  prep();
  int n;
  cin >> n;
  bool conn[n][n];
  memset(conn, false, sizeof(bool)*n*n);
  for (int i=0; i<n; i++){
      string s;
      cin >> s;
      for (int j=0; j<n; j++){
          if (s[j] == '1'){
              graph[i].push_back(j);
              conn[i][j] = true;
          }
      }
  }
  // start from 0
  int first = 0;
  // start from something connected to 0
  int second = graph[0][0];
  bip(first, 1);
  if (!good){
      memset(vals, 0, sizeof(int)*n);
      memset(vis, false, sizeof(bool)*n);
      good = true;
      bip(second, 1);
      if (!good){
          cout << -1;
          return 0;
      }
  }
  int dists[n+1][n+1];
  for (int i=0; i<n; i++){
      for (int j=0; j<n; j++){
          if (conn[i][j]){
              dists[i][j] = 1;
          }else if (i == j){
              dists[i][j] = 0;
          }else{
              dists[i][j] = 1000000000;
          }
      }
  }
  for (int i=0; i<n; i++){
      for (int j=0; j<n; j++){
          for (int k=0; k<n; k++){
              dists[j][k] = min(dists[j][k], dists[j][i]+dists[i][k]);
          }
      }
  }
  int maxest = 0;
  for (int i=0; i<n; i++){
      for (int j=0; j<n; j++){
          maxest = max(dists[i][j], maxest);
      }
  }
  cout << maxest+1;
  return 0; 
}