/// Swift5 -> Swift2.2

extension String {
    // split(separator:maxSplits:omittingEmptySubsequences:)
    func split(separator separator: Character) -> [String] {
        return self.characters.split(separator).map(String.init)
    }
}
extension Array {
    // init(repeating:count:)
    init(repeating: Element, count: Int) {
        self.init(count: count, repeatedValue: repeating)
    }
    // lastIndex(where:)
    func lastIndex(where predicate: (Element) -> Bool) -> Int? {
      	for i in stride(from: count - 1, through: 0, by: -1) {
          	if predicate(self[i]) {
              	return i
            }
        }
      	return nil
    }
}
extension Array where Element: Comparable {
    // sorted()
    func sorted() -> [Element] {
        return self.sort( { $0 < $1 } )
    }
    // max()
    func max() -> Element? {
        guard self.count > 0 else { return nil }
        return self.reduce(self.first!) { return Swift.max($0, $1) }
    }
}
// stride(from:through:by:)
func stride(from start: Int, through end: Int, by stride: Int) -> StrideThrough<Int> {
    return start.stride(through: end, by: stride)
}
// stride(from:to:by)
func stride(from start: Int, to end: Int, by stride: Int) -> StrideTo<Int> {
    return start.stride(to: end, by: stride)
}

/// end

let input = readLine()!.split(separator: " ").map { Int($0)! }
let N = input[0]
let M = input[1]

var edges = Array(repeating: [Int](), count: N + 1)

for _ in 0 ..< M {
    let edge = readLine()!.split(separator: " ").map { Int($0)! }
    let sourceNode = edge[0]
    let destinationNode = edge[1]
    edges[sourceNode].append(destinationNode)
}

var dp = Array(repeating: Int.min, count: N + 1)

func memorization(startNode: Int) -> Int {
    guard dp[startNode] == Int.min else { return dp[startNode] }

    var result = 0
    for destinationNode in edges[startNode] {
        result = max(result, memorization(destinationNode) + 1)
    }
    dp[startNode] = result
    return result
}

var result = 0
for i in stride(from: 1, through: N, by: 1) {
    result = max(result, memorization(i))
}
print(result)
