Problem:
Score : 100 points

Problem 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.

Constraints

All values in input are integers.

2 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq x_i, y_i \leq N

All pairs (x_i, y_i) are distinct.

G does not contain directed cycles.

Input

Input is given from Standard Input in the following format:

N M
x_1 y_1
x_2 y_2
:
x_M y_M

Output

Print the length of the longest directed path in G.

Sample Input 1

4 5
1 2
1 3
3 2
2 4
3 4

Sample Output 1

3

The red directed path in the following figure is the longest:

Sample Input 2

6 3
2 3
4 5
5 6

Sample Output 2

2

The red directed path in the following figure is the longest:

Sample Input 3

5 8
5 3
2 3
2 4
5 2
5 1
1 4
4 3
1 3

Sample Output 3

3

The red directed path in the following figure is one of the longest:

Solution in Rust (1.15.1) (judge verdict: Accepted)

// This code is generated by [cargo-atcoder](https://github.com/tanakh/cargo-atcoder)
// Original source code:
/*
use libprocon::*;

#[derive(Debug, Clone, Copy)]
struct Edge {
    from: usize,
    to: usize,
}

#[derive(Debug, Clone)]
struct Vertex {
    n_links: usize,
    inflows: Vec<usize>,
    outflows: Vec<usize>,
}

fn main() {
    let (N, M) = read!(usize, usize);
    let mut edges: Vec<Edge> = Vec::with_capacity(M);
    for _ in 0..M {
        let (from, to) = read!(usize, usize);
        edges.push(Edge {
            from: from - 1,
            to: to - 1,
        }); // 0-based
    }

    let mut vertexes: Vec<Vertex> = (0..N)
        .map(|_| Vertex {
            n_links: 0,
            inflows: vec![],
            outflows: vec![],
        })
        .collect();
    for edge in edges.iter() {
        vertexes[edge.to].n_links += 1;
        vertexes[edge.to].inflows.push(edge.from);
        vertexes[edge.from].outflows.push(edge.to);
    }

    let mut no_inflows = vertexes
        .iter()
        .enumerate()
        .filter_map(|(i, v)| if v.n_links == 0 { Some(i) } else { None })
        .collect::<Vec<_>>();
    let mut sorted = vec![];

    while !no_inflows.is_empty() {
        let n = no_inflows.pop().unwrap();
        sorted.push(n);
        for &out in vertexes[n].outflows.clone().iter() {
            vertexes[out].n_links -= 1;
            if vertexes[out].n_links == 0 {
                no_inflows.push(out);
            }
        }
    }

    // dp[i] := 頂点iにいくための最長経路の長さ
    let mut dp = vec![-1_i32; N];
    let mut ans = 0;
    for &s in sorted.iter() {
        let len_longest = match vertexes[s].inflows.iter().map(|&i| dp[i]).max() {
            Some(-1) | None => 0,
            Some(x) => x + 1,
        };
        dp[s] = len_longest;
        ans = std::cmp::max(ans, len_longest);
    }

    println!("{}", ans);
}
*/

fn main() {
    let exe = "/tmp/bin29FF8A0F";
    std::io::Write::write_all(&mut std::fs::File::create(exe).unwrap(), &decode(BIN)).unwrap();
    std::fs::set_permissions(exe, std::os::unix::fs::PermissionsExt::from_mode(0o755)).unwrap();
    std::process::exit(std::process::Command::new(exe).status().unwrap().code().unwrap())
}

fn decode(v: &str) -> Vec<u8> {
    let mut ret = vec![];
    let mut buf = 0;
    let mut tbl = vec![64; 256];
    for i in 0..64 { tbl[TBL[i] as usize] = i as u8; }
    for (i, c) in v.bytes().filter_map(|c| { let c = tbl[c as usize]; if c < 64 { Some(c) } else { None } }).enumerate() {
        match i % 4 {
            0 => buf = c << 2,
            1 => { ret.push(buf | c >> 4); buf = c << 4; }
            2 => { ret.push(buf | c >> 2); buf = c << 6; }
            3 => ret.push(buf | c),
            _ => unreachable!(),
        }
    }
    ret
}

const TBL: &'static [u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const BIN: &'static str = "<base64-encoded ELF executable removed>";