#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
typedef unsigned long long int ull;
typedef long double ld;
typedef pair<lli,lli> pll;
typedef std::vector<lli> vll;
typedef std::vector<pll> vpll;
typedef std::vector<bool> vbb;
typedef map<lli,lli>mll;
typedef set<lli> sll;
typedef multiset<lli> msll;

lli MOD=1e9 +7;
lli INF=1e18;
#define forr(i,p,n) for(i=p; i<n; i++)
#define be(a) a.begin(),a.end()
#define mp make_pair
#define um unordered_map
#define eb emplace_back 
#define pb push_back 
#define F first
#define S second
#define all(a)     (a).begin(),(a).end()
#define PI 3.14159265358979323846
#define lb lower_bound
#define ub upper_bound
#define endl "\n"
lli bitc(lli n,lli x){return ((n>>x)&1);}
lli __gcd(lli a,lli b){return b==0?a:__gcd(b,a%b);}
lli sub(lli a,lli b,lli p=MOD){return ((a%p)-(b%p)+p)%p;}
lli mult(lli a,lli b, lli p=MOD) {return ((a%p)*(b%p))%p;}
lli add(lli a, lli b, lli p=MOD) {return (a%p + b%p)%p;}
// lli add(lli a,lli b,lli p=MOD){//if(a+b>=p){//return (a+b)-p;//  }//return a+b;// }
lli fpow(lli n, lli k, lli p = MOD) {lli r = 1; while(k > 0) {if (k & 1) r = r * n%p; n = n * n%p; k = k >> 1;} return r;}
lli inv(lli a, lli p = MOD) {return fpow(a, p - 2, p);}
lli fdiv(lli a,lli b,lli p=MOD){
	lli yinv=inv(b);
	lli ans=(a*yinv)%p;
	return ans;
}
template<typename T>
istream &operator>>(istream &in, vector<T> &a) {
	for (auto &item : a) {
		in >> item;
	}
	return in;
}
template<typename T,typename U>
ostream &operator<<(ostream &out, pair<T,U> &a) {
	cout<<a.F<<" "<<a.S;
	return out;
}
template<typename T,typename U>
istream &operator>>(istream &out, pair<T,U> &a) {
	cin>>a.F>>a.S;
	return out;
}
template<typename T,typename U>
ostream &operator<<(ostream &out, map<T,U> &a) {
	for (auto &item : a) {
		out << item << endl;
	}
	return out;
}

template<typename T>
ostream &operator<<(ostream &out, vector<T> &a) {
	for (auto &item : a) {
		out << item << " ";
	}
	return out;
}

template<typename T>
ostream &operator<<(ostream &out, vector<vector<T>> &a) {
	for (auto &item : a) {
		out << item << "\n";
	}
	return out;
}
#define print(a) for(auto p:a) cout<<p<<" "; cout<<endl;
#define read(a) for(auto &p:a)cin>>p>>endl;

std::vector<bool> is_prime;
std::vector<lli> primes;
void sieve(lli n){
	is_prime.resize(n+2,true);
	primes.clear();
	lli p;
	for(p=2;p*p<=n;p++){
		if(is_prime[p]){
			lli i;
			for(i=p*p;i<=n;i+=p){
				is_prime[i]=false;
			}
		}
	}
	is_prime[0]=is_prime[1]=false;
	lli i;
	for(i=2;i<=n;i++){
		if(is_prime[i]){
			primes.eb(i);
		}
	}
}
mll prime_factors(lli n){	
	mll s;
	lli i;
	lli tc=0;
	while(n%2==0){
		tc++;
		n/=2;
	}
	if(tc>0){
		s[2]=tc;
	}
	for(i=3;i<=sqrt(n);i+=2){
		tc=0;
		while(n%i==0){
			tc++;
			n/=i;
		}
		if(tc>0){
			s[i]=tc;
		}
	}
	if(n>2){
		s[n]+=1;
	}
	return s;
}

//FACTORIAL
std::vector<lli> fact_vec;
void fact_fun(lli n){fact_vec.resize(n+10);lli i;fact_vec[0]=1;for(i=1;i<=n+2;i++){fact_vec[i]=(fact_vec[i-1]*i)%MOD;}}

//declare

class Sol{
public:  	
	lli n;
	vector<vll>graph;
	vbb vis;
	vll dp;
	Sol(){				
		lli m;
		cin>>n>>m;
		graph.resize(n);
		vis.resize(n,false);
		dp.resize(n,0);
		while(m--){
			lli u,v;
			cin>>u>>v;
			--u;
			--v;
			graph[u].eb(v);
		}
		lli i;
		forr(i,0,n){
			if(!vis[i]){
				dfs(i);
			}
		}
		lli ans=0;
		for(auto p:dp){
			ans=max(p,ans);
		}
		cout<<ans<<endl;


	}		
	void dfs(lli src){
		vis[src]=true;
		for(auto p:graph[src]){
			if(!vis[p]){
				dfs(p);
			}
			dp[src]=max(dp[src],1+dp[p]);
		}
	}
};

int main(){     
	lli i,j;    
	ios::sync_with_stdio(false);
	cin.tie(0);

// #ifndef ONLINE_JUDGE	
// 	freopen("input.txt", "r", stdin);
// 	freopen("output.txt", "w", stdout);
// #endif	

	Sol sol;
}   


Measured memory_bytes: 7680