// Original C++ solution (slower):
/*

██╗  ██╗ █████╗ ██████╗ ███████╗███████╗███╗   ███╗        ██╗  ██╗██╗  ██╗ █████╗ ██╗     ███████╗██████╗

██║ ██╔╝██╔══██╗██╔══██╗██╔════╝██╔════╝████╗ ████║        ██║ ██╔╝██║  ██║██╔══██╗██║     ██╔════╝██╔══██╗

█████╔╝ ███████║██████╔╝█████╗  █████╗  ██╔████╔██║        █████╔╝ ███████║███████║██║     █████╗  ██║  ██║

██╔═██╗ ██╔══██║██╔══██╗██╔══╝  ██╔══╝  ██║╚██╔╝██║        ██╔═██╗ ██╔══██║██╔══██║██║     ██╔══╝  ██║  ██║

██║  ██╗██║  ██║██║  ██║███████╗███████╗██║ ╚═╝ ██║███████╗██║  ██╗██║  ██║██║  ██║███████╗███████╗██████╔╝

╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚══════╝╚═╝     ╚═╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚══════╝╚═════╝

Believe in yourself ,( try and try and then try ), You can do it

*/

#define _CRT_SECURE_NO_WARNINGS

#include<bits/stdc++.h>

#include<unordered_map>

#define endl "\n"

#define Ceil(x,y) ((x+y-1)/y)

#define clr(arr, x) memset(arr, x, sizeof arr)

#define all(v) v.begin(),v.end()

#define allr(s) s.rbegin(),s.rend()

#define rt(s) return cout<<s,0

#define watch(x) cout<<(#x)<<" = "<<x<<endl

#define sz(s)	(int)(s.size())

#define OO 0x3f3f3f3f3f3f3f3fLL

const int oo = 0x3f3f3f3f, mod = 1e9 + 7;

using namespace std;

typedef long long ll;

typedef long double ld;

typedef unsigned long long ull;

int dx[] { 1, -1, 0, 0, 1, 1, -1, -1 };

int dy[] { 0, 0, 1, -1, 1, -1, 1, -1 };

void K_K(){ 

	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

}

vector<vector<int>>gr;

int dp[100005];

int dfs(int node){

	if (!sz(gr[node]))

		return 0;

	int &ret = dp[node];

	if (~ret)

		return ret;

	for (auto child : gr[node]){

		ret = max(ret, dfs(child) + 1);

	}

	return ret;

}

int main(){

	K_K();

	int n, m;

	cin >> n >> m;

	gr.resize(n + 1);

	clr(dp, -1);

	for (int i = 0; i < m; i++){

		int u, v;

		cin >> u >> v;

		gr[u].push_back(v);

	}

	int ans = 0;

	for (int i = 1; i <= n; i++){

		dfs(i);

		ans = max(ans, dp[i]);

	}

	cout << ans;

}

// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

#define si(a) scanf("%d", &a)

#define fore(i,a,b) for(int i = a; i < b; ++i)

using namespace std;

typedef long long ll;

typedef pair<int,int> pi;

typedef vector<int> vi;

vector<vector<int> > gr;

vi out;

vi ans;

vector<bool> visited;

vi aux;

void dfs(int u){

	visited[u] = true;

	//ans[u] = max(ans[u], val);

	fore(j,0,gr[u].size()){

		if(!visited[ gr[u][j] ])

			dfs(gr[u][j]);

		//ans[u] = max(ans[u], ans[ gr[u][j] ] + 1);

	}

	aux.push_back(u);

}

void solve(){

	int n,m;

	si(n); si(m);

	int x,y;

	gr.assign(n+1,vector<int>());

	out.assign(n+1,0);

	ans.assign(n+1,0);

	vector<pi> inv(m);

	aux.reserve(n);

	vi in(n+1);

	visited.assign(n+1,false);

	fore(i,0,m){

		si(x);si(y);

		inv[i] = pi(x,y);

		out[x]++;

		in[y]++;

	}

	fore(i,1,n+1)

		gr[i].reserve( in[i] );

	fore(i,0,m){

		x = inv[i].first;

		y = inv[i].second;

		gr[x].push_back(y);

	}

		

	fore(i,1,n+1)

		if(!visited[i])

			dfs(i);

	vi dp(n+1);

	//printf("aux: ");for(int i:aux) printf("%d ", i);printf("\n");

	for(int v: aux){

		if(gr[v].size() == 0)

			dp[v] = 0;

		else{

			int k = 0;

			for(int u: gr[v])

				k = max(k, dp[u]);

			dp[v] = k+1;

		}

	}

	int anss = 0;

	//printf("dp: ");for(int i:dp) printf("%d ", i);printf("\n");

	

	for(int i: dp)

		anss = max(anss, i);

	

	printf("%d\n", anss);

}

int main(){

	solve();

	return 0;

}

// Fastest known solution for this problem: