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.42.0) (judge verdict: Wrong Answer)

// -*- coding:utf-8-unix -*-

use std::cmp::*;
use std::collections::*;
use std::fs::File;
use std::io::prelude::*;
use std::io::*;
use std::vec;

const INF: i64 = 1223372036854775807;
const MEM_SIZE: usize = 202020;
const MOD: i64 = 1000000007;
use std::cmp::*;
use std::collections::*;
use std::io::stdin;
use std::io::stdout;
use std::io::Write;
#[allow(dead_code)]
fn read<T: std::str::FromStr>() -> T {
    let mut s = String::new();
    std::io::stdin().read_line(&mut s).ok();
    s.trim().parse().ok().unwrap()
}
#[allow(dead_code)]
fn read_vec<T: std::str::FromStr>() -> Vec<T> {
    read::<String>()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}
#[allow(dead_code)]
fn read_vec2<T: std::str::FromStr>(n: u32) -> Vec<Vec<T>> {
    (0..n).map(|_| read_vec()).collect()
}

#[allow(unused_macros)]
macro_rules! p {
    ([$($x:expr), *]) => {{
        let mut f = true;
        $(
            print!("{}{}", if f {""} else {" "}, $x);
            f = false;
        )*
78786    print!("\n");
    }};
    ($x:expr) => {{
        let mut f = true;
        for a in $x.iter() {
            print!("{}{}", if f {""} else {" "}, a);
            f = false;
        }
        print!("\n");
    }};
}
#[allow(dead_code)]
fn readii() -> (i64, i64) {
    let mut str = String::new();
    let _ = stdin().read_line(&mut str).unwrap();
    let mut iter = str.split_whitespace();
    (
        iter.next().unwrap().parse::<i64>().unwrap(),
        iter.next().unwrap().parse::<i64>().unwrap(),
    )
}
#[allow(dead_code)]
fn readuu() -> (usize, usize) {
    let mut str = String::new();
    let _ = stdin().read_line(&mut str).unwrap();
    let mut iter = str.split_whitespace();
    (
        iter.next().unwrap().parse::<usize>().unwrap(),
        iter.next().unwrap().parse::<usize>().unwrap(),
    )
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($e:expr),*) => {
        #[cfg(debug_assertions)]
        $({
            let (e, mut err) = (stringify!($e), std::io::stderr());
            writeln!(err, "{} = {:?}", e, $e).unwrap()
        })*
    };
}

#[allow(dead_code)]
fn vector_accumulation(vec: &Vec<i64>) -> Vec<i64> {
    let mut res = Vec::new();
    let size = vec.len();
    res.push(0);
    for i in 0..size {
        res.push(vec[i]);
    }
    for i in 0..size {
        res[i + 1] += res[i];
    }
    res
}

#[allow(dead_code)]
pub fn gcd(mut a: i64, mut b: i64) -> i64 {
    if (a < b) {
        let t = a;
        a = b;
        b = t;
    }
    if b == 0 {
        a
    } else {
        gcd(b, a % b)
    }
}

#[allow(dead_code)]
pub fn bipartite_matching(g: &[Vec<usize>]) -> usize {
    fn dfs(
        v: usize,
        g: &[Vec<usize>],
        mat: &mut [Option<usize>],
        used: &mut [usize],
        id: usize,
    ) -> bool {
        used[v] = id;
        for &u in &g[v] {
            if mat[u].is_none()
                || used[mat[u].unwrap()] != id && dfs(mat[u].unwrap(), g, mat, used, id)
            {
                mat[v] = Some(u);
                mat[u] = Some(v);
                return true;
            }
        }
        false
    }
    let mut res = 0;
    let mut mat = vec![None; g.len()];
    let mut used = vec![0; g.len()];
    for v in 0..g.len() {
        if mat[v].is_none() && dfs(v, g, &mut mat, &mut used, v + 1) {
            res += 1;
        }
    }
    res
}

fn bipartiate_graph_judgement(
    v: usize,
    c: i64,
    color: &mut Vec<i64>,
    graph: &Vec<Vec<usize>>,
) -> bool {
    color[v] = c;
    // println!("{:?}", c);
    for nv in graph[v].iter() {
        if color[*nv] != -1 {
            if color[*nv] == c {
                return false;
            };

            continue;
        }
        if !bipartiate_graph_judgement(*nv, 1 - c, color, &graph) {
            return false;
        }
    }

    true
}

fn tree_diameter_dfs(v: usize, p: usize, depth: &mut Vec<i64>, graph: &Vec<Vec<usize>>) {
    let mut res: (i64) = (0);
    if (p != INF as usize) {
        depth[v] = depth[p] + 1;
    } else {
        depth[v] = 0;
    }
    // println!("{:?}", v);

    for nv in graph[v].iter() {
        if (*nv == p || depth[*nv] != -1) {
            continue;
        }
        tree_diameter_dfs(*nv, v, depth, graph);
    }
    // return res;
}

fn tree_diameter(graph: &Vec<Vec<usize>>) -> i64 {
    let mut depth: Vec<i64> = vec![-1; graph.len()];
    tree_diameter_dfs(0, INF as usize, &mut depth, &graph);
    let mut d = (0, 0);
    for i in 0..depth.len() {
        if (d.1 < depth[i]) {
            d = (i, depth[i])
        }
    }

    let mut depth: Vec<i64> = vec![-1; graph.len()];
    tree_diameter_dfs(d.0, INF as usize, &mut depth, &graph);
    let mut d = (0, 0);
    for i in 0..depth.len() {
        if (d.1 < depth[i]) {
            d = (i, depth[i])
        }
    }

    return d.1;
}

fn solve() {
    let n: usize = read();
    let mut vv: Vec<Vec<i64>> = vec![vec![0; (n) as usize]; (n) as usize];
    for i in 0..n {
        let s: String = read();
        let mut va = s.as_bytes().to_vec();
        for j in 0..n {
            vv[i][j] = va[j] as i64 - '0' as i64;
        }
    }

    let mut graph: Vec<Vec<usize>> = vec![vec![0; (0) as usize]; (n) as usize];
    for i in 0..n {
        for j in 0..n {
            if (vv[i][j] == 1) {
                graph[i].push(j);
            }
        }
    }
    // println!("{:?}", graph);
    let mut color: Vec<i64> = vec![-1; n];
    let flg = bipartiate_graph_judgement(0, 0, &mut color, &graph);
    // println!("{:?}", color);
    if flg == false {
        println!("-1");
    } else {
        println!("{}", tree_diameter(&graph) + 1);
    }

    return;
}
fn main() {
    solve()
}