You are given 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 if it's possible to divide the vertices into non-empty sets V_1, ..., V_k such that every edge connects two vertices belonging to adjacent sets. If yes, find the maximum possible number of sets, k, in such a division. Constraints: 2 ≤ N ≤ 200, S_{i,j} is 0 or 1, S_{i,i} is 0, S_{i,j}=S_{j,i}, the given graph is connected, and N is an integer. Input is given in the format: N, followed by the grid S. Output -1 if it's impossible to divide the vertices into sets satisfying the condition; otherwise, print the maximum possible number of sets, k. Examples of input and output are provided.

# Buggy version:
import sys

INF = 10 ** 8
N = int(input())
S = []
for _ in range(N):
    S.append(list(map(int,list(input()))))

color = [0] * N

def dfs(x, c):
    color[x] = c
    for i in range(N):
        if S[x][i] and color[i] == c:
            return False
        if S[x][i] and color[i] == 0 and not dfs(i, -c):
            return False
    return True

for i in range(N):
    if color[i] == 0 and not dfs(i, 1):
        print(-1)
        sys.exit()

d = [[INF if S[i][j] == 0 else S[i][j] for i in range(N)] for j in range(N)]

for k in range(N):
    for i in range(N):
        for j in range(N):
            d[i][j] = min(d[i][j], d[i][k] + d[k][j])

ans = 0

for i in range(N):
    for j in range(N):
        if d[i][j] != INF:
            ans = max(ans, d[i][j])
print(ans)

# Fixed version:
import sys

INF = 10 ** 8
N = int(input())
S = []
for _ in range(N):
    S.append(list(map(int,list(input()))))

color = [0] * N

def dfs(x, c):
    color[x] = c
    for i in range(N):
        if S[x][i] and color[i] == c:
            return False
        if S[x][i] and color[i] == 0 and not dfs(i, -c):
            return False
    return True

for i in range(N):
    if color[i] == 0 and not dfs(i, 1):
        print(-1)
        sys.exit()

d = [[INF if S[i][j] == 0 else S[i][j] for i in range(N)] for j in range(N)]

for k in range(N):
    for i in range(N):
        for j in range(N):
            if i != j:
                d[i][j] = min(d[i][j], d[i][k] + d[k][j])

ans = 0

for i in range(N):
    for j in range(N):
        if d[i][j] != INF:
            ans = max(ans, d[i][j]+1)
print(ans)

# Buggy version:
import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time,copy,functools
from collections import deque

sys.setrecursionlimit(10**7)
inf = 10**20
mod = 10**9 + 7

DR = [1, -1, 0, 0]
DC = [0, 0, 1, -1]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x)-1 for x in sys.stdin.readline().split()]
def LF(): return [float(x) for x in sys.stdin.readline().split()]
def LS(): return sys.stdin.readline().split()
def I(): return int(sys.stdin.readline())
def F(): return float(sys.stdin.readline())
def S(): return input()
     
def main():
    N = I()
    adj = []
    for i in range(N):
        adj.append(S())

    def bfs(v):
        group = [-1] * N
        q = deque([(v, 0)])
        group[v] = 0
        while q:
            cur_v, gid = q.popleft()
            for next_v in range(N):
                if adj[cur_v][next_v] == '0':
                    continue
                if group[next_v] != -1:
                    if abs(group[cur_v] - group[next_v]) > 1:
                        return -1
                    else:
                        continue
                group[next_v] = gid + 1
                q.append((next_v, gid+1))
        return max(group) + 1

    ans = -1
    for i in range(N):
        ans = max(ans, bfs(i))

    print(ans)

main()



# Fixed version:
import math,string,itertools,fractions,heapq,collections,re,array,bisect,sys,random,time,copy,functools
from collections import deque

sys.setrecursionlimit(10**7)
inf = 10**20
mod = 10**9 + 7

DR = [1, -1, 0, 0]
DC = [0, 0, 1, -1]

def LI(): return [int(x) for x in sys.stdin.readline().split()]
def LI_(): return [int(x)-1 for x in sys.stdin.readline().split()]
def LF(): return [float(x) for x in sys.stdin.readline().split()]
def LS(): return sys.stdin.readline().split()
def I(): return int(sys.stdin.readline())
def F(): return float(sys.stdin.readline())
def S(): return input()
     
def main():
    N = I()
    adj = []
    for i in range(N):
        adj.append(S())

    def bfs(v):
        group = [-1] * N
        q = deque([(v, 0)])
        group[v] = 0
        while q:
            cur_v, gid = q.popleft()
            for next_v in range(N):
                if adj[cur_v][next_v] == '0':
                    continue
                if group[next_v] != -1:
                    if abs(group[cur_v] - group[next_v]) > 1:
                        return -1
                    if group[cur_v] == group[next_v]:
                        return -1
                    else:
                        continue
                group[next_v] = gid + 1
                q.append((next_v, gid+1))
        return max(group) + 1

    ans = -1
    for i in range(N):
        ans = max(ans, bfs(i))

    print(ans)

main()

# Buggy version:
import sys,queue,math,copy,itertools,bisect,collections,heapq

def main():
    NI = lambda : int(sys.stdin.readline())

    N = NI()
    S = [[int(x) for x in sys.stdin.readline().rstrip()] for _ in range(N)]

    max_k = 0

    for i in range(N):
        node = [-1] * N
        q = collections.deque()
        q.append((i,1))
        node[i] = 1
        s = copy.deepcopy(S)
        f = True
        while q:
            v,d = q.popleft()
            for j in range(N):
                if s[i][j] == 0: continue
                if node[j] == d+1 or node[j] == d-1: continue
                if node[j] < 0:
                    node[j] = d+1
                    q.append((j,d+1))
                else:
                    f = False
                    break
            else:
                continue
            break
        if f: max_k = max(max_k,max(node))
    if max_k == 0:
        print(-1)
    else:
        print(max_k)

if __name__ == '__main__':
    main()

# Fixed version:
import sys,queue,math,copy,itertools,bisect,collections,heapq

def main():
    NI = lambda : int(sys.stdin.readline())

    N = NI()
    S = [[int(x) for x in sys.stdin.readline().rstrip()] for _ in range(N)]

    max_k = 0

    for i in range(N):
        node = [-1] * N
        q = collections.deque()
        q.append((i,1))
        node[i] = 1
        f = True
        while q:
            v,d = q.popleft()
            for j in range(N):
                if S[v][j] == 0: continue
                if node[j] == d+1 or node[j] == d-1: continue
                if node[j] < 0:
                    node[j] = d+1
                    q.append((j,d+1))
                else:
                    f = False
                    break
            else:
                continue
            break
        if f: max_k = max(max_k,max(node))
    if max_k == 0:
        print(-1)
    else:
        print(max_k)

if __name__ == '__main__':
    main()

# Buggy version:
#!/usr/bin/python3
# -*- coding:utf-8 -*-

from collections import defaultdict
from queue import deque

def main():
  n = int(input())
  graph = defaultdict(list)
  
  def is_bt():
    def bfs():
      colors = [-1] * len(graph)
      dq = deque()
      dq.append(0)
      colors[0] = 0
      while dq:
        inode = dq.popleft()
        for ichild in graph[inode]:
          if colors[ichild] == -1:
            colors[ichild] = abs(colors[inode]-1)
            dq.append(ichild)
          else:
            if colors[ichild] == colors[inode]:
              return False
      return True
    return bfs()
  
  def wf(edges):
    dp = edges
    for k in range(len(graph)):
      for i in range(len(graph)):
        for j in range(len(graph)):
          dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])
    return dp
  
  edges = [[n+1] * n for _ in range(n)]  
  for i in range(n):
    for j, c in enumerate(input().strip()):
      if c == '1':
        graph[i].append(j)
        edges[i][j] = 1
    edges[i][i] = 0
  graph = dict(graph)
    
#   if not is_bt():
#     print(-1)
#     return
  print(max([max(x) for x in wf(edges)]) + 1)
  
if __name__=='__main__':
  main()



# Fixed version:
#!/usr/bin/python3
# -*- coding:utf-8 -*-

from collections import defaultdict
from queue import deque

def main():
  n = int(input())
  graph = defaultdict(list)
  
  def is_bt():
    def bfs():
      colors = [-1] * len(graph)
      dq = deque()
      dq.append(0)
      colors[0] = 0
      while dq:
        inode = dq.popleft()
        for ichild in graph[inode]:
          if colors[ichild] == -1:
            colors[ichild] = abs(colors[inode]-1)
            dq.append(ichild)
          else:
            if colors[ichild] == colors[inode]:
              return False
      return True
    return bfs()
  
  def wf(edges):
    dp = edges
    for k in range(len(graph)):
      for i in range(len(graph)):
        for j in range(len(graph)):
          dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])
    return dp
  
  edges = [[n+1] * n for _ in range(n)]  
  for i in range(n):
    for j, c in enumerate(input().strip()):
      if c == '1':
        graph[i].append(j)
        edges[i][j] = 1
    edges[i][i] = 0
  graph = dict(graph)
    
  if not is_bt():
    print(-1)
    return
  print(max([max(x) for x in wf(edges)]) + 1)
  
if __name__=='__main__':
  main()

# Buggy version:
n = int(input())
S = []
for i in range(n):
    S.append(input())
color = [-1]*n #0:黒, 1:白
color[0] = 0
stack = [0]
colored = [0]*n
colored[0] = 1
while len(stack) != 0:
    temp = stack.pop()
    col = color[temp]
    cur = S[temp]
    for j in range(n):
        if cur[j] == '1':
            if colored[j] != 0:
                if color[j] == col:
                    print(-1)
                    exit()
            else:
                if col == 1:
                    color[j] = 0
                else:
                    color[j] = 1
                colored[j] = 1
                stack.append(j)
maxdist = 0
dist = []
for i in range(n):
    d = [10**7]*n
    d[i] = 0
    dist.append(d)
for i in range(n):
    for j in range(n):
        if S[i][j] == '1':
            dist[i][j] = 1
for i in range(n):
    for k in range(n):
        for j in range(n):
            dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j])
            if dist[i][j] != 10**7:
                maxdist = max(maxdist, dist[i][j])
print(maxdist)


# Fixed version:
n = int(input())
S = []
for i in range(n):
    S.append(input())
color = [-1]*n #0:黒, 1:白
color[0] = 0
stack = [0]
colored = [0]*n
colored[0] = 1
while len(stack) != 0:
    temp = stack.pop()
    col = color[temp]
    cur = S[temp]
    for j in range(n):
        if cur[j] == '1':
            if colored[j] != 0:
                if color[j] == col:
                    print(-1)
                    exit()
            else:
                if col == 1:
                    color[j] = 0
                else:
                    color[j] = 1
                colored[j] = 1
                stack.append(j)
maxdist = 0
dist = []
for i in range(n):
    d = [10**10]*n
    d[i] = 0
    dist.append(d)
for i in range(n):
    for j in range(n):
        if S[i][j] == '1':
            dist[i][j] = 1
for k in range(n):
    for i in range(n):
        for j in range(n):
            dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j])
for i in range(n):
    for j in range(n):
        maxdist = max(maxdist, dist[i][j])
print(maxdist+1)

# Buggy version:
from collections import deque
n=int(input())
g=[[] for i in range(n)]
for i in range(n):
    p=list(str(input()))
    for j in range(n):
        if p[j]=='1':
            g[i].append(j)
q=deque([0])
v=[-1]*n
v[0]=0
while q:
    p=q.popleft()
    for i in g[p]:
        if v[i]==-1:
            v[i]=1-v[p]
            q.append(i)
        else:
            if v[i]!=1-v[p]:
                print(-1)
                exit()
q=deque([0])
v=[0]*n
v[0]=1
while q:
    p=q.popleft()
    for i in g[p]:
        if v[i]==0:
            v[i]=1+v[p]
            q.append(i)
s=v.index(max(v))
q=deque([s])
v=[0]*n
v[0]=1
while q:
    p=q.popleft()
    for i in g[p]:
        if v[i]==0:
            v[i]=1+v[p]
            q.append(i)
print(max(v))

# Fixed version:
from collections import deque
n=int(input())
g=[[] for i in range(n)]
for i in range(n):
    p=list(str(input()))
    for j in range(n):
        if p[j]=='1':
            g[i].append(j)
q=deque([0])
v=[-1]*n
v[0]=0
while q:
    p=q.popleft()
    for i in g[p]:
        if v[i]==-1:
            v[i]=1-v[p]
            q.append(i)
        else:
            if v[i]!=1-v[p]:
                print(-1)
                exit()
ans=0
for s in range(n):
    q=deque([s])
    v=[0]*n
    v[s]=1
    while q:
        p=q.popleft()
        for i in g[p]:
            if v[i]==0:
                v[i]=1+v[p]
                q.append(i)
    ans=max(ans,max(v))
print(ans)

# Buggy version:
# AGC039B - Graph Partition (153ms)
from collections import deque


def is_bipartite() -> bool:
    stack, color = [(1, 1)], [0] * (N + 1)
    color[1] = 1
    while stack:
        v, cur_color = stack.pop()
        next_color = -cur_color
        for u in E[v]:
            if color[u] == cur_color:
                return False
            if not color[u]:
                color[u] = next_color
                stack.append((u, next_color))
    return True


def bfs(source: int) -> int:
    queue = deque([source])
    dist = [0] * (N + 1)  # dist[i] := distance from V_source to V_i
    dist[start] = 1
    while queue:
        v = queue.popleft()
        cur = dist[v]
        for u in E[v]:
            if not dist[u]:
                dist[u] = cur + 1
                queue.append(u)
    return max(dist)


def main():
    # if bipartite graph -> diameter of the graph + 1
    global N, E
    N, *S = open(0).read().split()
    N = int(N)
    E = [0] + [[i for i, flg in enumerate(s, 1) if flg == "1"] for s in S]
    if is_bipartite():
        ans = max(bfs(i) for i in range(1, N + 1))
        print(ans)
    else:
        print(-1)


if __name__ == "__main__":
    main()

# Fixed version:
# AGC039B - Graph Partition (153ms)
from collections import deque


def is_bipartite() -> bool:
    stack, color = [(1, 1)], [0] * (N + 1)
    color[1] = 1
    while stack:
        v, cur_color = stack.pop()
        next_color = -cur_color
        for u in E[v]:
            if color[u] == cur_color:
                return False
            if not color[u]:
                color[u] = next_color
                stack.append((u, next_color))
    return True


def bfs(source: int) -> int:
    queue = deque([source])
    dist = [0] * (N + 1)  # dist[i] := distance from V_source to V_i
    dist[source] = 1
    while queue:
        v = queue.popleft()
        cur = dist[v]
        for u in E[v]:
            if not dist[u]:
                dist[u] = cur + 1
                queue.append(u)
    return max(dist)


def main():
    # if bipartite graph -> diameter of the graph + 1
    global N, E
    N, *S = open(0)
    N = int(N)
    E = [0] + [[i for i, flg in enumerate(s, 1) if flg == "1"] for s in S]
    if is_bipartite():
        ans = max(bfs(i) for i in range(1, N + 1))
        print(ans)
    else:
        print(-1)


if __name__ == "__main__":
    main()

# Buggy version:
# AGC039B - Graph Partition
def is_bipartite() -> bool:
    stack = deque([(1, 1)])
    color = [-1] * (N + 1)
    color[1] = 1
    while stack:
        v, cur_color = stack.pop()
        next_color = cur_color ^ 1
        for u in E[v]:
            if color[u] == cur_color:
                return False
            if color[u] == -1:
                color[u] = next_color
                stack.append((u, next_color))
    return True


def bfs(start) -> int:
    que = deque([start])
    dist = [-1] * (N + 1)  # dist[i] := distance from V_start to V_i
    dist[start] = 0
    while que:
        v = que.popleft()
        cur = dist[v]
        for u in E[v]:
            if dist[u] == -1:
                dist[u] = cur + 1
                que.append(u)
    return max(dist)


def main():
    # if bipartite graph -> diameter of the graph + 1
    global N, E
    N, *S = open(0).read().split()
    N = int(N)
    E = [0] + [[i for i, flg in enumerate(s, 1) if flg == "1"] for s in S]
    if is_bipartite():
        ans = max(bfs(i) for i in range(1, N + 1)) + 1
        print(ans)
    else:
        print(-1)


if __name__ == "__main__":
    main()

# Fixed version:
# AGC039B - Graph Partition
from collections import deque


def is_bipartite() -> bool:
    stack = [(1, 1)]
    color = [-1] * (N + 1)
    color[1] = 1
    while stack:
        v, cur_color = stack.pop()
        next_color = cur_color ^ 1
        for u in E[v]:
            if color[u] == cur_color:
                return False
            if color[u] == -1:
                color[u] = next_color
                stack.append((u, next_color))
    return True


def bfs(start) -> int:
    que = deque([start])
    dist = [-1] * (N + 1)  # dist[i] := distance from V_start to V_i
    dist[start] = 0
    while que:
        v = que.popleft()
        cur = dist[v]
        for u in E[v]:
            if dist[u] == -1:
                dist[u] = cur + 1
                que.append(u)
    return max(dist)


def main():
    # if bipartite graph -> diameter of the graph + 1
    global N, E
    N, *S = open(0).read().split()
    N = int(N)
    E = [0] + [[i for i, flg in enumerate(s, 1) if flg == "1"] for s in S]
    if is_bipartite():
        ans = max(bfs(i) for i in range(1, N + 1)) + 1
        print(ans)
    else:
        print(-1)


if __name__ == "__main__":
    main()

# Buggy version:
from collections import deque
N = int(input())
X = [[] for _ in range(N)]
for i in range(N):
    s = input()
    for j in range(N):
        if s[j] == "1":
            X[i].append(j)

def bipartite(n, E):
    col = [-1] * n
    for i in range(n):
        if col[i] >= 0: continue
        que = deque([[i, 0]])
        f = 0
        while que:
            v, c = que.popleft()
            col[v] = c
            for ne in E[v]:
                if col[ne] == c:
                    f = 1
                    break
                if col[ne] < 0:
                    que.append([ne, 1-c])

            if f:
                break
    return 1-f

def BFS(n, E, i0=0):
    Q = deque([i0])
    D = [-1] * n
    D[i0] = 0
    while Q:
        x = Q.popleft()
        for c in E[x]:
            if D[c] == -1:
                D[c] = D[x] + 1
                Q.append(c)
    return D

if bipartite(N, X):
    print(max([max(BFS(N, X, i)) for i in range(N)])+1)
else:
    print(-1)
print("X =", X)
for i in range(N):
    print(i, BFS(N, X, i))

# Fixed version:
from collections import deque
N = int(input())
X = [[] for _ in range(N)]
for i in range(N):
    s = input()
    for j in range(N):
        if s[j] == "1":
            X[i].append(j)

def bipartite(n, E):
    col = [-1] * n
    f = 0
    for i in range(n):
        if col[i] >= 0: continue
        que = deque([[i, 0]])
        while que:
            v, c = que.popleft()
            if col[v] == -1:
                col[v] = c
            elif col[v] == c:
                continue
            else:
                f = 1
                break
            for ne in E[v]:
                if col[ne] == c:
                    f = 1
                    break
                if col[ne] < 0:
                    que.append([ne, 1-c])

            if f:
                break
        if f:
            break
    return 1-f

def BFS(n, E, i0=0):
    Q = deque([i0])
    D = [-1] * n
    D[i0] = 0
    while Q:
        x = Q.popleft()
        for c in E[x]:
            if D[c] == -1:
                D[c] = D[x] + 1
                Q.append(c)
    return D

if bipartite(N, X):
    print(max([max(BFS(N, X, i)) for i in range(N)])+1)
else:
    print(-1)

# Buggy version:
from collections import deque

n = int(input())
s = [input() for _ in range(n)]

# 二部グラフ判定
memo = [-1] * n
memo[0] = 0
q = deque((0, -1))
while q:
    v, p = q.popleft()
    for nv in range(n):
        if s[v][nv] == '1':
            if nv == p:
                continue
            if memo[nv] == -1:
                memo[nv] = (memo[v] + 1) % 2
                q.append((nv, v))
            else:
                if memo[nv] == memo[v]:
                    print(-1)
                    exit()

# ワーシャルフロイドでグラフの直径を求めてもよし
INF = float('inf')
dp = [[1 if c == '1' else INF for c in row] for row in s]

for i in range(n):
    dp[i][i] = 0

for k in range(n):
    for i in range(n):
        for j in range(n):
            dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])

dist = 0
for i in range(n):
    d = 0
    for j in range(n):
        d = max(d, dp[i][j])
    dist = max(d, dist)

print(dist+1)

# Fixed version:
from collections import deque

n = int(input())
s = [input() for _ in range(n)]

# 二部グラフ判定
memo = [-1] * n
memo[0] = 0
q = deque([(0, -1)])
while q:
    v, p = q.popleft()
    for nv in range(n):
        if s[v][nv] == '1':
            if nv == p:
                continue
            if memo[nv] == -1:
                memo[nv] = (memo[v] + 1) % 2
                q.append((nv, v))
            else:
                if memo[nv] == memo[v]:
                    print(-1)
                    exit()

# ワーシャルフロイドでグラフの直径を求めてもよし
INF = float('inf')
dp = [[1 if c == '1' else INF for c in row] for row in s]

for i in range(n):
    dp[i][i] = 0

for k in range(n):
    for i in range(n):
        for j in range(n):
            dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j])

dist = 0
for i in range(n):
    d = 0
    for j in range(n):
        d = max(d, dp[i][j])
    dist = max(d, dist)

print(dist+1)

# Buggy version:
from collections import deque

def solve(init):
  depth = 0
  groups = [INF for i in range(N)]
  q = deque()
  q.append(init)
  while len(q) > 0:
    u = q.popleft()
    groups[u] = depth
    for v in range(N):
      if M[u][v] == 0:
        continue
      if groups[v] != INF:
        if groups[v] == depth-1:
          continue
        else:
          return -1
      q.append(v)
    depth += 1
  return depth

N = int(input())
M = [list(map(int, list(input()))) for i in range(N)]
INF = 201

res = -1
for u in range(N):
  res = max(res, solve(u))

print(res)


# Fixed version:
from collections import deque

def solve(init):
  groups = [-1 for i in range(N)]
  groups[init] = 1
  q = deque()
  q.append(init)
  while len(q) > 0:
    u = q.popleft()
    for v in range(N):
      if M[u][v] == 0:
        continue
      if groups[v] != -1:
        if groups[v] == groups[u]-1 or groups[v] == groups[u]+1:
          continue
        else:
          return -1
      groups[v] = groups[u] + 1
      q.append(v)
  return max(groups)


N = int(input())
M = [list(map(int, list(input()))) for i in range(N)]

res = -1
for u in range(N):
  res = max(res, solve(u))

print(res)

# Buggy version:
import sys
from collections import deque
sys.setrecursionlimit(10**7)
n=int(input())
l=[list(input()) for i in range(n)]
colors = [0 for i in range(n)]
es=[[] for i in range(n)]
Edges=es
for i in range(n):
  for j in range(n):
    if l[i][j]=='1':
      es[i].append(j)
def dfs(v,color):
    colors[v] = color
    for to in es[v]:
        if colors[to] == color:
            return False
        if colors[to] == 0 and not dfs(to, -color):
            return False
    return True
 
def is_bipartite():
    return dfs(0,1)
if is_bipartite()==0:
  print(-1)
  sys.exit()


def bfs(v):
    Visited=[False]*n
    q=deque()
    q.append((v,0))
    Visited[v]=True
    ret=(v,0)
    while q:
        fr,dist=q.popleft()
        if ret[1]<dist:
            ret=(fr,dist)
        for to in Edges[fr]:
            if not Visited[to]:
                Visited[to]=True
                q.append((to,dist+1))
    return ret

(v,dist)=bfs(0)
(v,dist)=bfs(v)
if dist==1:
  print(3)
else:
  print(dist+1)

# Fixed version:
import sys
from collections import deque
sys.setrecursionlimit(10**7)
n=int(input())
l=[list(input()) for i in range(n)]
colors = [0 for i in range(n)]
es=[[] for i in range(n)]
Edges=es
for i in range(n):
  for j in range(n):
    if l[i][j]=='1':
      es[i].append(j)
def dfs(v,color):
    colors[v] = color
    for to in es[v]:
        if colors[to] == color:
            return False
        if colors[to] == 0 and not dfs(to, -color):
            return False
    return True
 
def is_bipartite():
    return dfs(0,1)
if is_bipartite()==0:
  print(-1)
  sys.exit()


def bfs(v):
    Visited=[False]*n
    q=deque()
    q.append((v,0))
    Visited[v]=True
    ret=(v,0)
    while q:
        fr,dist=q.popleft()
        if ret[1]<dist:
            ret=(fr,dist)
        for to in Edges[fr]:
            if not Visited[to]:
                Visited[to]=True
                q.append((to,dist+1))
    return ret

ans=[]
for i in range(n):
  ans.append(bfs(i)[1])
print(max(ans)+1)

# Buggy version:
n = int(input())
S = [list(map(int,input())) for i in range(n)]
Graph = [[] for i in range(n)]
for i in range(n):
    for j in range(n):
        if S[i][j]==1:
            Graph[i]+=[j]
colors = [0 for i in range(n)]

def is_bipartite(es):
    stack = [(0,1)]
    while stack:
        v,color = stack.pop()
        colors[v] = color
        for to in es[v]:
            if colors[to] == color:
                 return False
            if colors[to] == 0:
                 stack.append((to, -color))
    return True

if not is_bipartite(Graph):
    print(-1)
    exit()

S2 = [[float("inf") for i in range(n)] for i in range(n)]
for i in range(n):
    for j in range(n):
        if S[i][j]==1:
            S2[i][j]=1
        elif i==j:
            S2[i][j]=0

def warshall_floyd(d):
    for k in range(n):
        for i in range(n):
            for j in range(n):
                d[i][j] = min(d[i][j],d[i][k] + d[k][j])
    return d

warshall_floyd(S2)

diam = 0
for i in range(n):
    for j in range(n):
        diam = max(diam,S2[i][j])
print(diam)


# Fixed version:
n = int(input())
S = [list(map(int,input())) for i in range(n)]
Graph = [[] for i in range(n)]
for i in range(n):
    for j in range(n):
        if S[i][j]==1:
            Graph[i]+=[j]
colors = [0 for i in range(n)]

def is_bipartite(es):
    stack = [(0,1)]
    while stack:
        v,color = stack.pop()
        colors[v] = color
        for to in es[v]:
            if colors[to] == color:
                 return False
            if colors[to] == 0:
                 stack.append((to, -color))
    return True

if not is_bipartite(Graph):
    print(-1)
    exit()

S2 = [[float("inf") for i in range(n)] for i in range(n)]
for i in range(n):
    for j in range(n):
        if S[i][j]==1:
            S2[i][j]=1
        elif i==j:
            S2[i][j]=0

def warshall_floyd(d):
    for k in range(n):
        for i in range(n):
            for j in range(n):
                d[i][j] = min(d[i][j],d[i][k] + d[k][j])
    return d

warshall_floyd(S2)

diam = 0
for i in range(n):
    for j in range(n):
        diam = max(diam,S2[i][j])
print(diam+1)

# Buggy version:
def warshall_floyd(d):
    for k in range(n):
        for i in range(n):
            for j in range(n):
                d[i][j] = min(d[i][j],d[i][k] + d[k][j])
    return d
n = int(input())
d = [[float("inf") for i in range(n)] for i in range(n)] 
l=[[] for i in range(n)]
#d[u][v] : 辺uvのコスト(存在しないときはinf)
for i in range(n):
    s=input()
    for j in range(n):
        if s[j]=="1":
            d[i][j] = 1
            l[i].append([i,j])
for i in range(n):
    d[i][i] = 0
wf=warshall_floyd(d)
visited = [1]+[0 for i in range(n-1)]
"""
while 0 in visited:
    for i in l:
        if visited[i[0]]!=0:
            if visited[i[0]]==1:
                if visited[i[1]]==1:
                    print(-1)
                    exit()
                elif visited[i[1]]==0:
                    visited[i[1]]=-1
            else:
                if visited[i[1]]==-1:
                    print(-1)
                    exit()
                elif visited[i[1]]==0:
                    visited[i[1]]=1
"""
ans=0
for i in wf:
    ans=max(ans,max(i)+1)
print(ans)

# Fixed version:
#warshall_floyd法
def warshall_floyd(d):
    for k in range(n):
        for i in range(n):
            for j in range(n):
                d[i][j] = min(d[i][j],d[i][k] + d[k][j])
    return d
n = int(input())
d = [[float("inf") for i in range(n)] for i in range(n)] 
l=[]
#d[u][v] : 辺uvのコスト(存在しないときはinf)
for i in range(n):
    s=input()
    for j in range(n):
        if s[j]=="1":
            d[i][j] = 1
            l.append([i,j])
for i in range(n):
    d[i][i] = 0
wf=warshall_floyd(d)
visited = [1]+[0 for i in range(n-1)]
for _ in range(1000):
    for i in l:
        if visited[i[0]]!=0:
            if visited[i[0]]==1:
                if visited[i[1]]==1:
                    print(-1)
                    exit()
                elif visited[i[1]]==0:
                    visited[i[1]]=-1
            else:
                if visited[i[1]]==-1:
                    print(-1)
                    exit()
                elif visited[i[1]]==0:
                    visited[i[1]]=1
ans=0
for i in wf:
    ans=max(ans,max(i)+1)
print(ans)

# Buggy version:
#  --*-coding:utf-8-*--


def f(N, S, st):
    R = [0]*(N)

    Q = set([st])
    R[st] = 1
    idx = 1
    cnt = 0

    while(len(Q) > 0):
        Q2 = set()
        cnt += 1
        idx += 1
        
        for i in Q:
            for j, s in enumerate(S[i]):
                if s == '1':
                    if R[j] == idx - 1:
                        return -1
                    elif R[j] == 0:
                        R[j] = idx
                        Q2.add(j)
                    
        Q = Q2
        
    return cnt
        


def g(N, S):
    m = 0

    for i in range(N):
        k = f(N, S, i)
        if k == -1:
            return -1

        m = max(m, k)

    return m



def main():
    N = int(input())
    S = list(input() for _ in range(N))

    print(g(N, S))





# Fixed version:
#  --*-coding:utf-8-*--


def f(N, S, st):
    R = [0]*(N)

    Q = set([st])
    R[st] = 1
    idx = 1
    cnt = 0

    while(len(Q) > 0):
        Q2 = set()
        cnt += 1
        idx += 1
        
        for i in Q:
            for j, s in enumerate(S[i]):
                if s == '1':
                    if R[j] == idx - 1:
                        return -1
                    elif R[j] == 0:
                        R[j] = idx
                        Q2.add(j)
                    
        Q = Q2
        
    return cnt
        


def g(N, S):
    m = 0

    for i in range(N):
        k = f(N, S, i)
        if k == -1:
            return -1

        m = max(m, k)

    return m



def main():
    N = int(input())
    S = list(input() for _ in range(N))

    print(g(N, S))





if __name__ == '__main__':
    main()

# Buggy version:
from collections import deque

N = int(input())

minDist = [[1 if s == '1' else float('inf') for s in input()] for _ in range(N)]

for i in range(N):
    minDist[i][i] = 0

for k in range(N):
    for i in range(N):
        for j in range(N):
            if minDist[i][j] > minDist[i][k] + minDist[k][j]:
                minDist[i][j] = minDist[i][k] + minDist[k][j]

ans = 0
base = [d % 2 for d in minDist[0]]

for i in range(N):
    A = [0] * N
    for j, d in enumerate(minDist[i]):
        A[j] = (d + base[i]) % 2
        ans = max(ans, d)
    if A != base:
        print(-1)
        exit()

if ans % 2 == 1:
    print(0)
print(ans + 1)

# Fixed version:
from collections import deque

N = int(input())

minDist = [[1 if s == '1' else float('inf') for s in input()] for _ in range(N)]

for i in range(N):
    minDist[i][i] = 0

for k in range(N):
    for i in range(N):
        for j in range(N):
            if minDist[i][j] > minDist[i][k] + minDist[k][j]:
                minDist[i][j] = minDist[i][k] + minDist[k][j]

base = [d % 2 for d in minDist[0]]

for i in range(N):
    A = [0] * N
    for j, d in enumerate(minDist[i]):
        A[j] = (d + base[i]) % 2
    if A != base:
        print(-1)
        exit()

ans = max([max(D) for D in minDist]) + 1
print(ans)