// Slower C++ solution:
#include<iostream>

#include<iomanip>

#include<cmath>

#include<string>

#include<cctype>

#include<algorithm>

#include<set>

#include<map>

#include<stack>

#include<queue>

#include<cstring>

//#include<windows.h>

//#include<time.h>

#define pb push_back

#define ppb pop_back

#define fi first

#define se second

#define mer make_pair

#define mme memset

using namespace std;



const double pie1=3.1415926;//π1

const double pie2=3.14159265358979;//π2

const double pie3=3.14159265358979323846;//π3

const int vbi=999999999;

const int vli=-vbi;

const long long vbl=999999999999999999;

const long long vll=-vbl;



typedef long long ll;

typedef pair<int,int> pii;

typedef pair<ll,ll> pll;

typedef pair<pii,int> piii;

typedef pair<pii,pii> pi4;

typedef pair<pll,ll> plll;

typedef pair<int,pii> ipii;

typedef pair<ll,pll> lpll;

typedef pair<pll,pll> pl4;

typedef vector<int> vi;

typedef vector<ll> vl;

typedef vector<pii> vpi;

typedef vector<pll> vpl;

typedef set<int> sti;

typedef set<ll> stl;

typedef set<pii> spi;

typedef set<pll> spl;

priority_queue<int> pqi;

priority_queue<ll> pql;

queue<int> qi;

queue<ll> ql;



/*void bin_v(){

	char bin[1000];

	gets(bin);

}*/



bool pss(int a){

	for(int i=2;i<=sqrt(a);i++)

		if(a%i==0)

			return false;

	return true;

}

/////////////////////////////////////////////////////////////////////////////////////////

int n,m;

vector<int> v[100010];

int d[100010];

int dp[100010];



int main(){

	//my name is Veex_WCY

	ios::sync_with_stdio(false);

	cin>>n>>m;

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

		int a,b;

		cin>>a>>b;

		v[a].pb(b);

		d[b]++;

	}

	stack<int> st;

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

		if(d[i]==0)

			st.push(i);

	while(!st.empty()){

		int x=st.top();

		st.pop();

		for(int i=0;i<v[x].size();i++){

			int ne=v[x][i];

			if(dp[x]+1>dp[ne])

				dp[ne]=dp[x]+1;

			d[ne]--;

			if(d[ne]==0)

				st.push(ne);

		}

	}

	int maxn=0;

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

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

	cout<<maxn;

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 3.236857234025629x):
#include <bits/stdc++.h>

typedef long long ll;

#define endl '\n'

#define pq priority_queue <pair<ll, ll>, vector<pair<ll, ll>>, greater<pair<ll, ll>>> 

#define graph1 vector<vector<pair<ll,ll>>>

#define graph vector<vector<ll>>

#define pq1 priority_queue<pair<ll, pair<ll, ll>>, vector<pair<ll, pair<ll,ll>>>, greater<pair<ll, pair<ll, ll>>>>

#define loop(i,a,b) for (ll i = a; i < b; i++)

#define fast ios::sync_with_stdio(0); cin.tie(0);

using namespace std;

bool visited[100005];

graph g;

ll maxx = 0;

void dfs(int node,  int dp[], bool vis[])

{

	

	vis[node] = true;



	for (int i = 0; i < g[node].size(); i++) {



		if (!vis[g[node][i]])

			dfs(g[node][i], dp, vis);



		dp[node] = max(dp[node], 1 + dp[g[node][i]]);

	}

}





int findLongestPath(int n)

{

	

	int dp[n + 1];

	memset(dp, 0, sizeof dp);



	

	bool vis[n + 1];

	memset(vis, false, sizeof vis);



	

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

		if (!vis[i])

			dfs(i, dp, vis);

	}



	int ans = 0;



	// Traverse and find the maximum of all dp[i] 

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

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

	}

	return ans;

}



int main()

{



	ll n, m;

	cin >> n >> m;

	g.resize(n + 1);

	memset(visited, false, sizeof(visited));

	loop(i, 0, m)

	{

		ll u, v;

		cin >> u >> v;

		g[u].push_back(v);

	}

	cout << findLongestPath(n);

}