class Array
  def warshall_floyd
    v = size

    dist = map(&:dup)

    v.times do |k|
      v.times do |i|
        v.times do |j|
          cost = dist[i][k] + dist[k][j]
          dist[i][j] = cost if dist[i][j] > cost
        end
      end
    end

    dist
  end
end

N = gets.to_i
S = N.times.map { gets.chomp.chars.map(&:to_i) }


module Graph
  class Tree
    def initialize(edges)
      @edges = edges
    end

    def diameter
      r = @edges.keys.first
      v, _ = farthest_vertex(r)
      u, d = farthest_vertex(v)
      [v, u, d]
    end

    private

    def farthest_vertex(s)
      queue = [[s, 0]]
      dist = -1
      fv = -1
      visited = Hash.new(false)

      until queue.empty?
        v, d = queue.shift

        next if visited[v]
        visited[v] = true

        if dist < d
          dist = d
          fv = v
        end

        @edges[v].each do |u|
          queue.push([u, d + 1])
        end
      end

      [fv, dist]
    end
  end
end

edges = Hash.new { |h, k| h[k] = [] }
e = Array.new(N) { Array.new(N, Float::INFINITY) }

S.each_with_index do |row, i|
  row.each_with_index do |t, j|
    if i == j
      e[i][j] = 0
    end

    next if t.zero?

    e[i][j] = 1
    edges[i] << j
  end
end

e = e.warshall_floyd
tree = Graph::Tree.new(edges)

md = 0
s = -1

e.each_with_index do |row, i|
  row.each do |d, j|
    if md < d
      md = d
      s = i
    end
  end
end

# root, _, dist = tree.diameter

queue = [[s]]
visited = Hash.new(false)

until queue.empty?
  list = queue.shift

  next if list.empty?

  vs = []

  list.each do |v|
    visited[v] = true

    edges[v].each do |u|
      next if visited[u]

      vs << u
    end
  end

  vs.uniq!

  vs.each do |i|
    vs.each do |j|
      next if i == j

      if S[i][j] == 1
        puts -1
        exit
      end
    end
  end

  queue.push(vs)
end

puts md + 1
