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 Rust (1.15.1) (judge verdict: Accepted)

use std::cmp;
use std::collections::{BTreeSet, VecDeque};

const INF: usize = 1000000;
fn main() {
    let s = std::io::stdin();
    let mut sc = Scanner { stdin: s.lock() };
    let n: usize = sc.read();
    let edge: Vec<Vec<bool>> = (0..n)
        .map(|_| sc.chars().into_iter().map(|c| c == '1').collect())
        .collect();

    let mut ans: Option<usize> = None;
    for start in 0..n {
        if let Some(t) = bfs(start, &edge) {
            match ans {
                Some(cur) => ans = Some(cmp::max(cur, t)),
                None => ans = Some(t),
            }
        }
    }

    match ans {
        Some(ans) => println!("{}", ans),
        None => println!("-1"),
    }
}

fn bfs(start: usize, edge: &Vec<Vec<bool>>) -> Option<usize> {
    let n = edge.len();
    let mut distances = vec![vec![]; n];
    distances[start].push(0);
    let mut dist = vec![INF; n];
    dist[start] = 0;
    let mut q = VecDeque::new();
    q.push_back(start);
    while let Some(v) = q.pop_front() {
        for next in 0..n {
            if !edge[v][next] {
                continue;
            }
            let next_dist = dist[v] + 1;
            if dist[next] > next_dist {
                dist[next] = next_dist;
                distances[next].push(next_dist);
                q.push_back(next);
            } else if dist[next] < next_dist {
                distances[next].push(next_dist);
            }
        }
    }

    let mut set = BTreeSet::new();
    for i in 0..n {
        let min = distances[i][0];
        if distances[i].iter().any(|&x| (x - min) % 2 != 0) {
            return None;
        }
        set.insert(min);
    }
    Some(set.len())
}

pub struct Scanner<R> {
    stdin: R,
}

impl<R: std::io::Read> Scanner<R> {
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .stdin
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n')
            .take_while(|&b| b != b' ' && b != b'\n')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}