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: Wrong Answer)

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define endl "\n"
#define REP(i,a,n) for(int i=a;i<n;++i)
#define REPR(i,a,n) for(int i=a;i>n;--i)
#define RUP(a,b) ((a+b-1)/(b))
#define ALL(v) (v).begin(),(v).end()
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define MOD 1000000007
#define INF LLONG_MAX/2

typedef long long ll;
typedef pair<int,int> Pii;
typedef tuple<int,int,int> Tiii;
typedef vector<int> Vi;
typedef vector<Vi> VVi;
typedef vector<Pii> VPii;
typedef vector<string> Vs;

template<class T> inline bool chmax(T& a,T b){if(a<b){a=b;return 1;}return 0;}
template<class T> inline bool chmin(T& a,T b){if(a>b){a=b;return 1;}return 0;}
template<class T> void YesNo(T a) {cout<<(a?"Yes":"No")<<endl;}
template<class T> void YESNO(T a) {cout<<(a?"YES":"NO")<<endl;}
void vin(Vi &v){REP(i,0,(v).size()) cin>>v[i];}
void vin(Vi &v,Vi &v2){REP(i,0,(v).size()) cin>>v[i]>>v2[i];}
void vout(Vi &v){for(int i=0;i<(v).size();i++) cout<<v[i]<<" ";cout<<endl;}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int lcm(int a,int b){return a/gcd(a,b)*b;}
void uniq(Vi &v){sort(v.begin(),v.end()); v.erase(unique(v.begin(),v.end()),v.end());}
int ctoi(char c){if(c>='0'&&c<='9'){return c-'0';}return 0;}
void accum(Vi &v){REP(i,1,(v).size()) v[i]+=v[i-1];}
bool comp(Pii a,Pii b){
    if(a.second != b.second) return a.second<b.second;
    else return a.first<b.first;
}

bool flag=true;

void bfs(Vi &dist , int start , vector<VPii> connect){
    dist[start]=0;
    queue<Pii> q;
    q.push(mp(start,0));
    while(!q.empty()){
        int now,depth;
        tie(now,depth)=q.front();
        q.pop();
        dist[now]=depth;
        REP(i,0,connect[now].size()){
            int next=connect[now][i].first;
            if(dist[next]!=INF && (dist[next]-depth)%2==0){cout<<-1<<endl;flag=false;return;}
            if(dist[next]==INF) q.push(mp(next,depth+1));
        }
    }
}

void solve(long long n, std::vector<string> s){
    vector<vector<Pii>> connect(n);
    REP(i,0,n){
        REP(j,0,n){
            if(s[i][j]=='1'){
                connect[i].pb(mp(j,1));
                connect[j].pb(mp(i,1));
            }
        }
    }

    Vi dist(n,INF);
    bfs(dist,0,connect);
    if(!flag) return;
    // priority_queue<Tiii,vector<Tiii>,greater<Tiii>> q;
    // q.push(make_tuple(0,0,-1));
    // while(!q.empty()){
    //     int nowdist,now,past;
    //     tie(nowdist,now,past)=q.top();
    //     q.pop();
    //     if(nowdist>dist[now]) continue;
    //     dist[now]=nowdist;
    //     REP(i,0,connect[now].size()){
    //         int next=connect[now][i].first,cost=connect[now][i].second;
    //         if(next!=past && dist[next]!=INF && (nowdist+cost-dist[next])%2==1){cout<<-1<<endl;return;}
    //         if(next!=past && nowdist+cost<dist[next]){
    //             q.push(make_tuple(nowdist+cost,next,now));
    //             dist[next]=nowdist+cost;
    //         }
    //     }
    // }
    int tmps=-1,maxd=-1;
    REP(i,0,n){
        if(dist[i]>maxd){
            tmps=i;
            maxd=dist[i];
        }
    }

    // priority_queue<Tiii,vector<Tiii>,greater<Tiii>> q2;
    // Vi dist2(n,INF);
    // dist2[tmps]=0;
    // q2.push(make_tuple(0,tmps,-1));
    // while(!q2.empty()){
    //     int nowdist,now,past;
    //     tie(nowdist,now,past)=q2.top();
    //     q2.pop();
    //     if(nowdist>dist2[now]) continue;
    //     dist2[now]=nowdist;
    //     REP(i,0,connect[now].size()){
    //         int next=connect[now][i].first,cost=connect[now][i].second;
    //         if(next!=past && dist2[next]!=INF && (nowdist+cost-dist2[next])%2==1){cout<<-1<<endl;return;}
    //         if(next!=past && nowdist+cost<dist2[next]){
    //             q2.push(make_tuple(nowdist+cost,next,now));
    //             dist2[next]=nowdist+cost;
    //         }
    //     }
    // }

    Vi dist2(n,INF);
    bfs(dist2,tmps,connect);
    
    tmps=-1;
    maxd=-1;
    REP(i,0,n){
        if(dist2[i]>maxd){
            tmps=i;
            maxd=dist2[i];
        }
    }

    
    cout<<maxd+1<<endl;
}

// Generated by 1.1.5 https://github.com/kyuridenamida/atcoder-tools  (tips: You use the default template now. You can remove this line by using your custom template)
signed main(){
    long long N;
    scanf("%lld",&N);
    std::vector<string> S(N);
    for(int i = 0 ; i < N ; i++){
        cin>>S[i];
    }
    solve(N, std::move(S));
    return 0;
}