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 (Clang 3.8.0) (judge verdict: Accepted)

//{{{
#include<algorithm>
#include<cmath>
#include<deque>
#include<fstream>
#include<iomanip>
#include<iostream>
#include<map>
#include<numeric>
#include<queue>
#include<random>
#include<set>
#include<sstream>
#include<sys/time.h>
#include<unordered_map>
#include<unordered_set>
#include<vector>
using ll = long long;
enum : int { M = (int)1e9 + 7 };
enum : ll { MLL = (ll)1e18L + 9 };
using namespace std;
#ifdef LOCAL
#include"rprint2.hpp"
#else
#define FUNC(name) template <ostream& out = cout, class... T> void name(T&&...){ }
FUNC(printde) FUNC(printdbe) FUNC(printdwe) FUNC(printdu);
#endif
template <template <class T, class = std::allocator<T>> class V, class E>
istream& operator >> (istream& in, V<E>& v){ for(auto& e : v){ in >> e; } return in; }
//}}}

struct Graph{
    struct Node{
        vector<int> dests;
        int color = -1;
    };
    vector<Node> nodes;
    Graph(int num): nodes(num){ }
    int id(Node* n){ return n - &nodes[0]; }
    int id(Node& n){ return &n - &nodes[0]; }
    // void print(){ for(auto& node : nodes){ prints(id(node), node.dests); } }
    void add1Edge(int from, int dest){
        nodes[from].dests.push_back(dest);
    }
    void add2Edge2(int from, int dest){
        add1Edge(from, dest);
        add1Edge(dest, from);
    }
    bool isBipartile(int idx, int color = 0, int from = -1){
        if(nodes[idx].color == -1){
            nodes[idx].color = color;
        }else{
            return nodes[idx].color == color;
        }
        for(int didx : nodes[idx].dests){
            if(didx == from){ continue; }
            if(!isBipartile(didx, !color, idx)){
                return false;
            }
        }
        return true;
    }
    ll dijkstra(int start, int goal){
        struct DElem{
            int cost, dest;
            bool operator < (const DElem& e) const { return cost > e.cost; }
        };
        priority_queue<DElem> pq;
        pq.push({0, start});
        vector<int> visited(nodes.size());
        while(pq.size()){
            auto e = pq.top(); pq.pop();
            if(visited[e.dest]){ continue; }
            visited[e.dest] = true;
            if(e.dest == goal){
                return e.cost;
            }
            // for(auto& edge : nodes[e.dest].edges){
            //     pq.push({e.cost + edge.cost, edge.dest});
            // }
            for(int didx : nodes[e.dest].dests){
                pq.push({e.cost + 1, didx});
            }
        }
        return -1;
    }
};

int main(){
    cin.tie(0); ios::sync_with_stdio(false);
    int n; cin >> n;
    // vector<vector<int>> ss(n, vector<int>(n)); cin >> ss;
    Graph g(n);
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            char s; cin >> s;
            if(s == '1' && i < j){
                g.add2Edge2(i, j);
            }
        }
    }
    if(!g.isBipartile(0)){
        cout << -1 << '\n';
        return 0;
    }
    int ans = 0;
    for(int i = 0; i < n; i++){
        for(int j = i + 1; j < n; j++){
            int len = g.dijkstra(i, j);
            ans = max(ans, len);
        }
    }
    cout << ans + 1 << '\n';
}