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 (GCC 5.4.1) (judge verdict: Wrong Answer)

#include <float.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <math.h>
#ifdef __cplusplus
#include <bits/stdc++.h>
#endif

uint32_t nextpint(void){ char c=getchar_unlocked(); while(c<'0'||'9'<c) c=getchar_unlocked(); uint32_t x=0; while('0'<=c && c<='9'){ x=x*10+c-'0'; c=getchar_unlocked(); } return x; }
uint32_t nextstr(char *s){ char c=getchar_unlocked(); while(c==' '||c=='\n') c=getchar_unlocked(); uint32_t len=0; while(c!=' '&&c!='\n'){ *s++=c-'0'; len++; c=getchar_unlocked(); } *s='\0'; return len; }
void printint(uint32_t x){ if(x<0){x=-x; putchar_unlocked('-');}else if(x==0){putchar_unlocked('0');} int d=0; char s[10]; while(x){ s[d]='0'+x%10; x/=10; d++; } for (int i=d-1; i>=0; i--) putchar_unlocked(s[i]); putchar_unlocked('\n'); }

uint32_t n;
char s[200][201];
char cp[200];

bool mcp(int p){
	for(uint32_t i=0; i<n; i++){
		if(s[p][i]==1){
			if(cp[i]==0){
				cp[i]=3-cp[p];
				mcp(i);
			}else if(cp[i]==cp[p]){
				return false;
			}
		}
	}
	return true;
}

int main(void){
	n=nextpint();
	for(uint32_t i=0; i<n; i++){
		nextstr(s[i]);
	}
	for(uint32_t i=0; i<n; i++){
		if(cp[i]==0){
			cp[i]=1;
			if(!mcp(i)){
				puts("-1");
				return 0;
			}
		}
	}
	for(uint32_t k=0; k<n; k++){
		for(uint32_t i=0; i<n; i++){
			for(uint32_t j=0; j<n; j++){
				if(i!=j && s[i][k]!=0 && s[k][j]!=0){
					uint32_t S=s[i][k]+s[k][j];
					if(s[i][j]==0 || s[i][j]>S) s[i][j]=S;
				}
			}
		}
	}
	uint32_t max=0;
	for(uint32_t i=0; i<n; i++){
		for(uint32_t j=0; j<n; j++){
			//putchar(s[i][j]+'0');
			if(s[i][j]>max) max=s[i][j];
		}
		//putchar(10);
	}
	printint(max==0?n:max+1);
}