fun main(args: Array<String>) {
    val (N, M) = readLine()!!.split(" "). map { it.toInt() }
    val list = Array(N) { mutableListOf<Int>() }
    val sorted = mutableListOf<Int>() // ソートされたグラフ
    // 入次数
    val indegree = IntArray(N)
    for (i in 0 until M) {
        val (x, y) = readLine()!!.split(" "). map { it.toInt() }
        list[x-1].add(y-1)
        indegree[y-1]++ // 入次数をincrement
    }

    // 入次数が0の物がグラフの始点
    val st = mutableListOf<Int>() // 注意 : Stackの方が良い
    list.forEachIndexed { index, mutableList ->
        if (indegree[index] == 0) st.add(index)
    }

    // ソート
    while(st.isNotEmpty()) {
        val i = st[0]; st.removeAt(0)
        sorted.add(i) // ソート済みのリストに追加

        // 隣接する頂点
        list[i].forEach { j ->
            indegree[j]-- // 隣接する頂点の入次数をデクリメント
            if (indegree[j] == 0) st.add(j) // 入次数が0になればstに追加
        }
    }

    // 最長パスを判定
    val ans = IntArray(N)
    ans[0] = 0
    sorted.forEach { i ->
        list[i].forEach {
            ans[it] = Math.max(ans[it], ans[i] + 1)
        }
    }
    println(ans.max())
}