// Original C++ solution (slower):
#include<bits/stdc++.h> 



using namespace std;



typedef short sho;

typedef long long ll;

typedef unsigned long long ull;

typedef long double ld;

typedef double db;

typedef string str; 

 

typedef pair<int,int> pii;

typedef pair<ll,ll> pll; 

typedef pair<ld,ld> pld;

 

typedef vector<int> vi; 

typedef vector<ll> vl; 

typedef vector<ld> vd;

typedef vector<str> vs;

typedef vector<pii> vpi;

typedef vector<pll> vpl;

typedef vector<pld> vpd;



#define STDIO

#define mp make_pair 

#define FF first

#define SS second

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

#define begin(x) (x).begin() 

#define end(x) (x).end()

#define rbegin(x) (x).rbegin()

#define rend(x) (x).rend()

#define all(x) begin(x), end(x)

#define rall(x) rbegin(x), rend(x)

#define rsz resize

#define ins insert

#define ft front()

#define bk back()

#define pf push_front 

#define pb push_back

#define pp push

#define lb lower_bound

#define ub upper_bound



inline void checkmin(int &x, int y){x = min(x, y);}

inline void checkmax(int &x, int y){x = max(x, y);}

inline void sortsm(int &x, int &y) {int a = min(x, y), b = max(x, y); checkmin(x, a); checkmax(y, b);}

inline void sortbi(int &x, int &y) {sortsm(x, y); swap(x, y);}



const int maxn=1e5+10;



int n,m;

int x[maxn],y[maxn];

int degree[maxn];



vector<int> edge[maxn];

int dp[maxn];

queue<int> Q;

//bool vis[maxn];



int main() {

	#ifndef STDIO

		freopen("input.txt","r",stdin);

		freopen("output.txt","w",stdout);

	#endif

	ios::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);

    /* start code */

    memset(dp,0,sizeof dp);

    memset(degree,0,sizeof degree);

//  memset(vis,0,sizeof vis);

    cin>>n>>m;

    for(int i=1;i<=m;i++)

    {

    	cin>>x[i]>>y[i];

    	edge[x[i]].pb(y[i]);

    	degree[y[i]]++;

	}

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

	{

		if(!degree[i])

		{

//			vis[i]=true;

			Q.pp(i);

		}

	}

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

//	{

//		cout<<degree[i]<<" ";

//	}

//	cout<<endl;

	while(!Q.empty())

	{

		int now=Q.front();

//		cout<<now<<endl;

		Q.pop();

//		for(auto to : edge[now])

//		{

//			degree[to]--;

//		}

		for(auto to : edge[now])

		{

			dp[to]=max(dp[to],dp[now]+1);

			degree[to]--;

			if(!degree[to])

			{

				Q.pp(to);

			}

		}

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

//		{

//			if(!degree[i]&&!vis[i])

//			{

//				vis[i]=true;

//				Q.pp(i);

//			}

//		}

	}

	int ans=0;

	for(auto dist : dp)

	{

		checkmax(ans,dist);

	}

	cout<<ans<<endl;

    /* end code */

	return 0;

}

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



using namespace std;



typedef short sho;

typedef long long ll;

typedef unsigned long long ull;

typedef long double ld;

typedef double db;

typedef string str; 

 

typedef pair<int,int> pii;

typedef pair<ll,ll> pll; 

typedef pair<ld,ld> pld;

 

typedef vector<int> vi; 

typedef vector<ll> vl; 

typedef vector<ld> vd;

typedef vector<str> vs;

typedef vector<pii> vpi;

typedef vector<pll> vpl;

typedef vector<pld> vpd;



#define STDIO

#define mp make_pair 

#define FF first

#define SS second

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

#define begin(x) (x).begin() 

#define end(x) (x).end()

#define rbegin(x) (x).rbegin()

#define rend(x) (x).rend()

#define all(x) begin(x), end(x)

#define rall(x) rbegin(x), rend(x)

#define rsz resize

#define ins insert

#define ft front()

#define bk back()

#define pf push_front 

#define pb push_back

#define pp push

#define lb lower_bound 

#define ub upper_bound



inline void checkmin(int &x, int y){x = min(x, y);}

inline void checkmax(int &x, int y){x = max(x, y);}



const int maxn=1e5+10;



int n,m,x,y;



vector<int> edge[maxn];

int in[maxn],dp[maxn];



int main() {

	#ifndef STDIO

		freopen("input.txt","r",stdin);

		freopen("output.txt","w",stdout);

	#endif

	ios::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);

    /* start code */

    cin>>n>>m;

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

    {

    	cin>>x>>y;

    	edge[x].pb(y);

    	in[y]++;

	}

	queue<int> que;

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

	{

		if(in[i]==0)

		{

			que.pp(i);

		}

	}

	while(!que.empty())

	{

		int t=que.front();

		que.pop();

		for(auto i : edge[t])

		{

			checkmax(dp[i],dp[t]+1);

			in[i]--;

			if(!in[i])

			{

				que.pp(i);

			}

		}

	}

	cout<<*max_element(dp+1,dp+1+n)<<endl;

    /* end code */

	return 0;

}

// Fastest known solution for this problem: