import sys

input = sys.stdin.readline

sys.setrecursionlimit(10**7)

n, m = list(map(int, input().split()))

edges = [[] for _ in range(n)]

for _ in range(m):

    x, y = list([int(x)-1 for x in input().split()])

    edges[x].append(y)





def memoize(f):

    memo = [-1]*n



    def memoized(args):

        if memo[args] != -1:

            return memo[args]

        else:

            memo[args] = f(args)

            return memo[args]

    return memoized





@memoize

def longest_path(v):

    retval = 0

    for v2 in edges[v]:

        retval = max(retval, longest_path(v2)+1)

    return retval





ans = 0

for i in range(n):

    ans = max(ans, longest_path(i))

print(ans)
from collections import deque, defaultdict

import sys

input = sys.stdin.readline

n, m = list(map(int, input().split()))

edges = [[]for _ in range(n)]

dd = defaultdict(int)

for _ in range(m):

    x, y = list([int(x)-1 for x in input().split()])

    edges[x].append(y)

    dd[y] += 1



queue = deque([])

for i in range(n):

    if dd[i] == 0:

        queue.append(i)



toposorted = []

while queue:

    v = queue.popleft()

    toposorted.append(v)

    for v2 in edges[v]:

        if dd[v2] <= 0:

            continue

        dd[v2] -= 1

        if dd[v2] == 0:

            queue.append(v2)



dist = [0]*n

for i in range(n):

    v = toposorted[i]

    for v2 in edges[v]:

        if dist[v2] <= dist[v]-1:

            continue

        dist[v2] = dist[v]-1

print((-min(dist)))

import sys

input = sys.stdin.readline
sys.setrecursionlimit(10**7)
n, m = list(map(int, input().split()))
edges = [[] for _ in range(n)]
for _ in range(m):
    x, y = list([int(x) - 1 for x in input().split()])
    edges[x].append(y)


def memoize(f):
    memo = [-1] * n

    def memoized(args):
        if memo[args] != -1:
            return memo[args]
        else:
            memo[args] = f(args)
            return memo[args]

    return memoized


@memoize
def longest_path(v):
    retval = 0
    for v2 in edges[v]:
        retval = max(retval, longest_path(v2) + 1)
    return retval


ans = 0
for i in range(n):
    ans = max(ans, longest_path(i))
print(ans)

from collections import deque, defaultdict
import sys

input = sys.stdin.readline
n, m = list(map(int, input().split()))
edges = [[] for _ in range(n)]
dd = defaultdict(int)
for _ in range(m):
    x, y = list([int(x) - 1 for x in input().split()])
    edges[x].append(y)
    dd[y] += 1
queue = deque([])
for i in range(n):
    if dd[i] == 0:
        queue.append(i)
toposorted = []
while queue:
    v = queue.popleft()
    toposorted.append(v)
    for v2 in edges[v]:
        if dd[v2] <= 0:
            continue
        dd[v2] -= 1
        if dd[v2] == 0:
            queue.append(v2)
dist = [0] * n
for i in range(n):
    v = toposorted[i]
    for v2 in edges[v]:
        if dist[v2] <= dist[v] - 1:
            continue
        dist[v2] = dist[v] - 1
print((-min(dist)))

+from collections import deque, defaultdict -sys.setrecursionlimit(10**7) +dd = defaultdict(int) - - -def memoize(f): -    memo = [-1] * n - -    def memoized(args): -        if memo[args] != -1: -            return memo[args] -        else: -            memo[args] = f(args) -            return memo[args] - -    return memoized - - -@memoize -def longest_path(v): -    retval = 0 +    dd[y] += 1 +queue = deque([]) +for i in range(n): +    if dd[i] == 0: +        queue.append(i) +toposorted = [] +while queue: +    v = queue.popleft() +    toposorted.append(v) -        retval = max(retval, longest_path(v2) + 1) -    return retval - - -ans = 0 +        if dd[v2] <= 0: +            continue +        dd[v2] -= 1 +        if dd[v2] == 0: +            queue.append(v2) +dist = [0] * n -    ans = max(ans, longest_path(i)) -print(ans) +    v = toposorted[i] +    for v2 in edges[v]: +        if dist[v2] <= dist[v] - 1: +            continue +        dist[v2] = dist[v] - 1 +print((-min(dist)))