output_description: Print the length of the longest directed path in G.
  
  * * *
input_description: Input is given from Standard Input in the following format:
  
      
      
      N M
      x_1 y_1
      x_2 y_2
      :
      x_M y_M
attempt: #!/usr/bin/env python3
  # -*- coding: utf-8 -*-
  """
  Created on 2019/3/6
  Update on 2019/3/6
  Solved on 2019/3/  
  @author: shinjisu
  """
  
  
  # Educational Dynamic Programming
  # import math
  import numpy as np
  
  
  def getInt():
      return int(input())
  
  
  # def getIntList(): return [int(x) for x in input().split()]
  def getIntList():
      return np.array(input().split(), dtype=np.longlong)
  
  
  # def zeros(n): return [0]*n
  def zeros(n):
      return np.zeros(n, dtype=np.longlong)
  
  
  # def getIntLines(n): return [int(input()) for i in range(n)]
  def getIntLines(n):
      data = zeros(n)
      for i in range(n):
          data[i] = getInt()
      return data
  
  
  def getIntMat(n, m):  # n行に渡って、1行にm個の整数
      mat = zeros((n, m))
      dmp(mat)
      for i in range(n):
          mat[i] = getIntList()
      return mat
  
  
  # def zeros2(n, m): return [zeros(m)]*n # obsoleted zeros((n, m))で代替
  
  
  ALPHABET = [chr(i + ord("a")) for i in range(26)]
  DIGIT = [chr(i + ord("0")) for i in range(10)]
  N1097 = 10**9 + 7
  INF = 10**18
  
  
  def dmp(x, cmt=""):
      global debug
      if debug:
          if cmt != "":
              print(cmt, ":  ", end="")
          print(x)
      return x
  
  
  def find(frm, to, path):
      dmp((frm, to, path), "frm, to, path")
      if frm in path:
          return dmp(-1, "not found")
      elif frm == to:
          return dmp(0, "same")
      else:
          path = path + [frm]
          dmp(path)
          longest = -1
          for i in range(M):
              dmp(longest, "longest")
              if edge[i, 0] == frm:
                  if edge[i, 1] == to:
                      longest = max(longest, len(path))
                  else:
                      longest = max(longest, find(edge[i, 1], to, path))
          return longest
  
  
  def prob_G():  # Longest Path
      global N, M, edge
      N, M = getIntList()
      dmp((N, M), "N, M")
      edge = getIntMat(M, 2)
      dmp(edge, "edge")
      graph = zeros((N + 1, N + 1))
      dmp(graph, "graph")
      for i in range(1, N + 1):
          for j in range(1, N + 1):
              graph[i][j] = find(i, j, [])
      dmp(graph, "graph")
      return graph.max()
  
  
  debug = False  # True False
  ans = prob_G()
  print(ans)
  # for row in ans:
  #    print(row)
  
problem_description: Statement
  
  There is a directed graph G with N vertices and M edges. The vertices are
  numbered 1, 2, \ldots, N, and for each i (1 \leq i \leq M), the i-th directed
  edge goes from Vertex x_i to y_i. G **does not contain directed cycles**.
  
  Find the length of the longest directed path in G. Here, the length of a
  directed path is the number of edges in it.
samples: [{"input": "4 5\n    1 2\n    1 3\n    3 2\n    2 4\n    3 4", "output": "3\n    \n\nThe red directed path in the following figure is the longest:\n\n![](https://img.atcoder.jp/dp/longest_0_muffet.png)\n\n* * *"}, {"input": "6 3\n    2 3\n    4 5\n    5 6", "output": "2\n    \n\nThe red directed path in the following figure is the longest:\n\n![](https://img.atcoder.jp/dp/longest_1_muffet.png)\n\n* * *"}, {"input": "5 8\n    5 3\n    2 3\n    2 4\n    5 2\n    5 1\n    1 4\n    4 3\n    1 3", "output": "3\n    \n\nThe red directed path in the following figure is one of the longest:\n\n![](https://img.atcoder.jp/dp/longest_2_muffet.png)"}]