stablegradients/pie-gem5-pairs huggingface dataset:
// Slower C++ solution:
#include <iostream>

#include<bits/stdc++.h>



using namespace std;



int n,m;

vector<int>v[200005];

int ans=0,c=0;

int dp[200005];

int vis[200005];

int mx=0;

void dfs(int node){

    vis[node]=1;

    for(int j=0;j<v[node].size();j++){

            if(!vis[v[node][j]])

            dfs(v[node][j]);

        dp[node]=max(dp[node],dp[v[node][j]]+1);

        mx=max(mx,dp[node]);

    }

    }





int main()

{

    cin>>n>>m;

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

        int x,y;

        cin>>x>>y;

        v[x].push_back(y);

    }

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

    if(!vis[i]){

        dfs(i);

    }

   }

   cout<<mx;



    return 0;

}


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

using namespace std;

#define ll long long

#define ull unsigned long long

#define PII pair<int,int>

#define PSI pair<string,int>

#define PIII pair< int, pair<int,int> >

const int MaxN = 1e5+5;

vector<int> g[MaxN];

int dp[MaxN];

int N;



int dfs(int node){



    auto &ret = dp[node];

    if(ret!=-1) return ret;

    ret = 0;

    for(auto i: g[node])

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

    return ret;

}



void read(){



    int i,edge;

    memset(dp,-1,sizeof dp);

    cin>>N>>edge;

    for(i=0; i<edge; i++){

        int u,v;

        cin>>u>>v;

        g[u].push_back(v);

    }

}



void solve(){



    read();

    int res = 0;

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

        res = max( res, dfs(i) );

    }



    cout<< res << "\n";

}



int main(){



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

    ios_base::sync_with_stdio(false);

    cin.tie(nullptr);

    solve();

    return 0;

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

#include<bits/stdc++.h>



using namespace std;



int n,m;

vector<int>v[200005];

int ans=0,c=0;

int dp[200005];

int vis[200005];

int mx=0;

void dfs(int node){

    vis[node]=1;

    for(int j=0;j<v[node].size();j++){

            if(!vis[v[node][j]])

            dfs(v[node][j]);

        dp[node]=max(dp[node],dp[v[node][j]]+1);

        mx=max(mx,dp[node]);

    }

    }





int main()

{

    cin>>n>>m;

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

        int x,y;

        cin>>x>>y;

        v[x].push_back(y);

    }

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

    if(!vis[i]){

        dfs(i);

    }

   }

   cout<<mx;



    return 0;

}


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

 

using namespace std;

 

typedef long long ll;

typedef vector<ll> vi;

typedef long double td;

typedef vector<td> vd;

typedef pair<ll,ll> ii;

typedef vector<ii> vii; typedef vector<bool> vb;

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

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

#define forn(i, n) forr(i, 0, n)

#define pb push_back

#define mp make_pair

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

#define DBG(x) cerr << #x << " = " << (x) << endl

#define show(v,n) cerr << #v << " = "; forn(i,n) cerr << v[i] << " "; cerr << endl;

#define esta(x,c) ((c).find(x) != (c).end())

#define RAYA cerr << "===============================" << endl

int MAXN = 500005;



vector <int> v[100005];

vector <int> dp(100005,0);

vector <bool> visto(100005,false);



void DFS(int n)

{

	visto[n]=true;

	for(auto u : v[n])

	{

		if(!visto[u]) DFS(u);

		dp[n]=max(dp[n],dp[u]+1);

	}

}

 

int main()

{ 	

	FIN;

	#ifdef input

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

	#endif



	int n, m;

	cin >> n >> m;

	forn(i,m)

	{

		int x, y;

		cin >> x >> y;

		v[x].pb(y);

	}

	forn(i,n+1)

	{

		if(visto[i]==false) DFS(i);

	}

	int ans = 0;

	forn(i,n+1) ans = max(ans,dp[i]);

	cout << ans << endl;

    return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;



int n, m;

vector<int>ady[100001];

vector<int>topoSort;

vector<int>who[100001];

bool visitado[100001];

int memo[100001];



void dfs(int nodo){

    visitado[nodo] = true;

    for(int i : ady[nodo])

        if (!visitado[i])

            dfs(i);

    topoSort.push_back(nodo);

}



void topological_sort(){

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

        if(!visitado[i])

            dfs(i);

}



int dp(int nodo){

    if(who[nodo].size() == 0)//es nodo raiz

        return  1;

    if(memo[nodo])

        return memo[nodo];

    int Max = 0;

    for(auto i : who[nodo])

        memo[nodo] = max(memo[nodo], dp(i) + 1);

    return memo[nodo];

}



int maxPath(){

    topological_sort();

    //hacemos orden topologico

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

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

    // cout<<endl;

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

    //     cout<<i<<": ";

    //     for(auto j : who[i])

    //         cout<<j<<" ";

    //     cout<<endl;

    // }

    // cout<<endl;

    // exit(0);

    int Max = -1;

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

        Max = max(Max, dp(topoSort[i]));

    return Max;

}



int main(){



    cin.tie(0);

    ios_base::sync_with_stdio(0);



    cin>>n>>m;



    while(m--){

        int a, b;

        cin>>a>>b;

        ady[a].push_back(b);

        who[b].push_back(a);

    }

    cout<<maxPath() - 1;

}

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

 

using namespace std;

 

typedef long long ll;

typedef vector<ll> vi;

typedef long double td;

typedef vector<td> vd;

typedef pair<ll,ll> ii;

typedef vector<ii> vii; typedef vector<bool> vb;

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

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

#define forn(i, n) forr(i, 0, n)

#define pb push_back

#define mp make_pair

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

#define DBG(x) cerr << #x << " = " << (x) << endl

#define show(v,n) cerr << #v << " = "; forn(i,n) cerr << v[i] << " "; cerr << endl;

#define esta(x,c) ((c).find(x) != (c).end())

#define RAYA cerr << "===============================" << endl

int MAXN = 500005;



vector <int> v[100005];

vector <int> dp(100005,0);

vector <bool> visto(100005,false);



void DFS(int n)

{

	visto[n]=true;

	for(auto u : v[n])

	{

		if(!visto[u]) DFS(u);

		dp[n]=max(dp[n],dp[u]+1);

	}

}

 

int main()

{ 	

	FIN;

	#ifdef input

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

	#endif



	int n, m;

	cin >> n >> m;

	forn(i,m)

	{

		int x, y;

		cin >> x >> y;

		v[x].pb(y);

	}

	forn(i,n+1)

	{

		if(visto[i]==false) DFS(i);

	}

	int ans = 0;

	forn(i,n+1) ans = max(ans,dp[i]);

	cout << ans << endl;

    return 0;

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

#include<bits/stdc++.h>



using namespace std;



int n,m;

vector<int>v[200005];

int ans=0,c=0;

int dp[200005];

int vis[200005];

int mx=0;

void dfs(int node){

    vis[node]=1;

    for(int j=0;j<v[node].size();j++){

            if(!vis[v[node][j]])

            dfs(v[node][j]);

        dp[node]=max(dp[node],dp[v[node][j]]+1);

        mx=max(mx,dp[node]);

    }

    }





int main()

{

    cin>>n>>m;

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

        int x,y;

        cin>>x>>y;

        v[x].push_back(y);

    }

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

    if(!vis[i]){

        dfs(i);

    }

   }

   cout<<mx;



    return 0;

}


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

#define endl '\n'

using namespace std;



const int MXN = 1e5 + 5;

int n, m;

int dp[MXN];

vector<int> g[MXN];



int dfs(int u) {

    if(dp[u] != -1) return dp[u];

    int ans = 0;

    for(auto & v: g[u]) {

        ans = max(ans, dfs(v) + 1);

    }

    return dp[u] = ans;

}



int main() {

    ios_base::sync_with_stdio(false); cin.tie(NULL);

    cin >> n >> m;

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

        int u, v; cin >> u >> v;

        u--, v--;

        g[u].emplace_back(v);

    }

    memset(dp, -1, sizeof dp);

    int ans = 0;

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

        ans = max(ans, dfs(i));

    }

    cout << ans << endl;

    return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;



int n, m;

vector<int>ady[100001];

vector<int>topoSort;

vector<int>who[100001];

bool visitado[100001];

int memo[100001];



void dfs(int nodo){

    visitado[nodo] = true;

    for(int i : ady[nodo])

        if (!visitado[i])

            dfs(i);

    topoSort.push_back(nodo);

}



void topological_sort(){

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

        if(!visitado[i])

            dfs(i);

}



int dp(int nodo){

    if(who[nodo].size() == 0)//es nodo raiz

        return  1;

    if(memo[nodo])

        return memo[nodo];

    int Max = 0;

    for(auto i : who[nodo])

        memo[nodo] = max(memo[nodo], dp(i) + 1);

    return memo[nodo];

}



int maxPath(){

    topological_sort();

    //hacemos orden topologico

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

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

    // cout<<endl;

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

    //     cout<<i<<": ";

    //     for(auto j : who[i])

    //         cout<<j<<" ";

    //     cout<<endl;

    // }

    // cout<<endl;

    // exit(0);

    int Max = -1;

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

        Max = max(Max, dp(topoSort[i]));

    return Max;

}



int main(){



    cin.tie(0);

    ios_base::sync_with_stdio(0);



    cin>>n>>m;



    while(m--){

        int a, b;

        cin>>a>>b;

        ady[a].push_back(b);

        who[b].push_back(a);

    }

    cout<<maxPath() - 1;

}

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

#define endl '\n'

using namespace std;



const int MXN = 1e5 + 5;

int n, m;

int dp[MXN];

vector<int> g[MXN];



int dfs(int u) {

    if(dp[u] != -1) return dp[u];

    int ans = 0;

    for(auto & v: g[u]) {

        ans = max(ans, dfs(v) + 1);

    }

    return dp[u] = ans;

}



int main() {

    ios_base::sync_with_stdio(false); cin.tie(NULL);

    cin >> n >> m;

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

        int u, v; cin >> u >> v;

        u--, v--;

        g[u].emplace_back(v);

    }

    memset(dp, -1, sizeof dp);

    int ans = 0;

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

        ans = max(ans, dfs(i));

    }

    cout << ans << endl;

    return 0;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;

#define ALL(x) (x).begin(),(x).end()

#define uniq(x) (x).erase(unique(ALL(x)),(x).end())

#define SORT(x) sort(ALL(x))

#define REV(x) reverse(ALL(x))

#define foreach(it,x) for(__typeof((x).begin()) it=(x).begin();it!=(x).end();it++)

#define debug(x) cerr<<#x<<"="<<(x)<<endl

#define gett() cerr<<"Time:"<<clock()<<"ms."<<endl

#define ri(x) scanf("%d",&x)

#define rl(x) scanf("%lld",&x)

#define rlcfpoj(x) scanf("%I64d",&x)

#define pi(x) printf("%d",x)

#define pl(x) printf("%lld",x)

#define plcfpoj(x) printf("%I64d",x)

#define lfd() printf("\n")

#define sp() printf(" ")

#define inrep(x) int x;scanf("%d",&x);while(x--)

#define testbit(mask,i) (((mask)>>(i))&1)

#define setbit(mask,i) ((mask)|(1<<i))

#define delbit(mask,i) ((mask)^(1<<i))

int dp[100100];

int n,m;

vector<int> ga[100100];

int u,v;

int d(int x){

	if(dp[x]!=-1)

		return dp[x];

	int &res=dp[x];

	res=0;

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

		int y=ga[x][i];

		res=max(res,d(y)+1);

	}

	return res;

}

int main(){

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

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

	ios::sync_with_stdio(false);

	cin.tie(NULL);

	cout.tie(NULL);

	cin>>n>>m;

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

		cin>>u>>v;

		ga[u].push_back(v);

	}

	int res=0;

	memset(dp,-1,sizeof(dp));

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

		res=max(res,d(i));

	}

	cout<<res<<endl;

	return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.1173723468708967x):
#include<cstdio>

#include<math.h>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<set>

#include<map>

#include<queue>

using namespace std;

#define Case int t;scanf("%d", &t);while(t--)

typedef long long ll;

const int Max = 1e5 + 5;

const int INF = 0x3f3f3f3f;

const double PI = acos(-1.0);

int n, m;

int dp[Max];

int in[Max];

vector<int> G[Max];

queue<int> que;

int main(){

	cin >> n >> m;

	int u, v;

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

		cin >> u >> v;

		G[u].push_back(v);

		in[v]++;

	}



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

		if(!in[i]) que.push(i);

	}



	int ans = 0;

	while(!que.empty()){

		int now = que.front();

		que.pop();

		for(int i = 0; i < G[now].size(); i++){

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

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

			in[G[now][i]]--;

			if(!in[G[now][i]]) que.push(G[now][i]);

		}

	}



	cout << ans << endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>

#define F first

#define S second

#define T second.first

#define C second.second

#define FIO ios_base::sync_with_stdio(0);cin.tie(0);

using namespace std;

typedef long long ll;

typedef pair<int, int> pii;

typedef pair<int,pair<int,int>> piii;



const int N= 1e2+5, L = 14, OO = 0x3f3f3f3f;

const int M= 1e9+7;

const double ESP = 1e-8;



int n,m, u,v;

vector<int>adj[100005];

int dp[100005];



int solve(int u){

    int& ret = dp[u];

    if(~ret)return ret;



    ret = 0;

    for(int v: adj[u])

        ret = max(ret, solve(v)+1);



    return ret;

}



int main(){

    FIO

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

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

    cin>>n>>m;

    memset(dp, -1, sizeof dp);

    while(m--){

        cin>>u>>v;

        adj[u].push_back(v);

    }

    int ans = 0;

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

        ans = max(ans, solve(i));

    }

    cout<<ans;

}


// Faster C++ solution for the same problem (measured speedup: 1.1172459667791845x):
#include<cstdio>

#include<math.h>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<set>

#include<map>

#include<queue>

using namespace std;

#define Case int t;scanf("%d", &t);while(t--)

typedef long long ll;

const int Max = 1e5 + 5;

const int INF = 0x3f3f3f3f;

const double PI = acos(-1.0);

int n, m;

int dp[Max];

int in[Max];

vector<int> G[Max];

queue<int> que;

int main(){

	cin >> n >> m;

	int u, v;

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

		cin >> u >> v;

		G[u].push_back(v);

		in[v]++;

	}



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

		if(!in[i]) que.push(i);

	}



	int ans = 0;

	while(!que.empty()){

		int now = que.front();

		que.pop();

		for(int i = 0; i < G[now].size(); i++){

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

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

			in[G[now][i]]--;

			if(!in[G[now][i]]) que.push(G[now][i]);

		}

	}



	cout << ans << endl;

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

#include<bits/stdc++.h>



using namespace std;



int n,m;

vector<int>v[200005];

int ans=0,c=0;

int dp[200005];

int vis[200005];

int mx=0;

void dfs(int node){

    vis[node]=1;

    for(int j=0;j<v[node].size();j++){

            if(!vis[v[node][j]])

            dfs(v[node][j]);

        dp[node]=max(dp[node],dp[v[node][j]]+1);

        mx=max(mx,dp[node]);

    }

    }





int main()

{

    cin>>n>>m;

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

        int x,y;

        cin>>x>>y;

        v[x].push_back(y);

    }

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

    if(!vis[i]){

        dfs(i);

    }

   }

   cout<<mx;



    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.8249134626691799x):
#include<cstdio>

#include<math.h>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<set>

#include<map>

#include<queue>

using namespace std;

#define Case int t;scanf("%d", &t);while(t--)

typedef long long ll;

const int Max = 1e5 + 5;

const int INF = 0x3f3f3f3f;

const double PI = acos(-1.0);

int n, m;

int dp[Max];

int in[Max];

vector<int> G[Max];

queue<int> que;

int main(){

	cin >> n >> m;

	int u, v;

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

		cin >> u >> v;

		G[u].push_back(v);

		in[v]++;

	}



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

		if(!in[i]) que.push(i);

	}



	int ans = 0;

	while(!que.empty()){

		int now = que.front();

		que.pop();

		for(int i = 0; i < G[now].size(); i++){

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

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

			in[G[now][i]]--;

			if(!in[G[now][i]]) que.push(G[now][i]);

		}

	}



	cout << ans << endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>





using namespace std;

typedef long long ll;

typedef unsigned long long ull;

typedef double dd;

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

#define endl "\n"

#define clr(n, r) memset(n,r,sizeof(n));



void fast() {

    cin.tie(0);

    cin.sync_with_stdio(0);

}



int OO = 100000000,n,m;

int dp[100009];

vector<vector<int>>edges(1e5);

int ans(int i){

    int &ret=dp[i];

    if(~ret)return ret;

    if(i==n+1||edges[i].empty())return 0;

    ret =0;

    for (int j = 0; j <edges[i].size() ; ++j) {

        ret=max (ret,1+ans(edges[i][j]));

    }

    return ret;

}







int main() {

    fast();

    cin>>n>>m;

    clr(dp,-1);

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

        int a,b;cin>>a>>b;

        edges[a].push_back(b);

    }

    int s=0;

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

     s=max(s,ans(j));

    }

    cout<<s;

}

// Faster C++ solution for the same problem (measured speedup: 1.1242583312498133x):
#include<cstdio>

#include<math.h>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<set>

#include<map>

#include<queue>

using namespace std;

#define Case int t;scanf("%d", &t);while(t--)

typedef long long ll;

const int Max = 1e5 + 5;

const int INF = 0x3f3f3f3f;

const double PI = acos(-1.0);

int n, m;

int dp[Max];

int in[Max];

vector<int> G[Max];

queue<int> que;

int main(){

	cin >> n >> m;

	int u, v;

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

		cin >> u >> v;

		G[u].push_back(v);

		in[v]++;

	}



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

		if(!in[i]) que.push(i);

	}



	int ans = 0;

	while(!que.empty()){

		int now = que.front();

		que.pop();

		for(int i = 0; i < G[now].size(); i++){

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

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

			in[G[now][i]]--;

			if(!in[G[now][i]]) que.push(G[now][i]);

		}

	}



	cout << ans << endl;

}
// Slower C++ solution:
#include <bits/stdc++.h>

using namespace std;

#define ll long long

#define ull unsigned long long

#define PII pair<int,int>

#define PSI pair<string,int>

#define PIII pair< int, pair<int,int> >

const int MaxN = 1e5+5;

vector<int> g[MaxN];

int dp[MaxN];

int N;



int dfs(int node){



    auto &ret = dp[node];

    if(ret!=-1) return ret;

    ret = 0;

    for(auto i: g[node])

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

    return ret;

}



void read(){



    int i,edge;

    memset(dp,-1,sizeof dp);

    cin>>N>>edge;

    for(i=0; i<edge; i++){

        int u,v;

        cin>>u>>v;

        g[u].push_back(v);

    }

}



void solve(){



    read();

    int res = 0;

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

        res = max( res, dfs(i) );

    }



    cout<< res << "\n";

}



int main(){



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

    ios_base::sync_with_stdio(false);

    cin.tie(nullptr);

    solve();

    return 0;

}


// Faster C++ solution for the same problem (measured speedup: 1.1185753962180742x):
#include<cstdio>

#include<math.h>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<set>

#include<map>

#include<queue>

using namespace std;

#define Case int t;scanf("%d", &t);while(t--)

typedef long long ll;

const int Max = 1e5 + 5;

const int INF = 0x3f3f3f3f;

const double PI = acos(-1.0);

int n, m;

int dp[Max];

int in[Max];

vector<int> G[Max];

queue<int> que;

int main(){

	cin >> n >> m;

	int u, v;

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

		cin >> u >> v;

		G[u].push_back(v);

		in[v]++;

	}



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

		if(!in[i]) que.push(i);

	}



	int ans = 0;

	while(!que.empty()){

		int now = que.front();

		que.pop();

		for(int i = 0; i < G[now].size(); i++){

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

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

			in[G[now][i]]--;

			if(!in[G[now][i]]) que.push(G[now][i]);

		}

	}



	cout << ans << endl;

}
// Slower C++ solution:
#include<bits/stdc++.h>

using namespace std;



int n, m;

vector<int>ady[100001];

vector<int>topoSort;

vector<int>who[100001];

bool visitado[100001];

int memo[100001];



void dfs(int nodo){

    visitado[nodo] = true;

    for(int i : ady[nodo])

        if (!visitado[i])

            dfs(i);

    topoSort.push_back(nodo);

}



void topological_sort(){

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

        if(!visitado[i])

            dfs(i);

}



int dp(int nodo){

    if(who[nodo].size() == 0)//es nodo raiz

        return  1;

    if(memo[nodo])

        return memo[nodo];

    int Max = 0;

    for(auto i : who[nodo])

        memo[nodo] = max(memo[nodo], dp(i) + 1);

    return memo[nodo];

}



int maxPath(){

    topological_sort();

    //hacemos orden topologico

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

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

    // cout<<endl;

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

    //     cout<<i<<": ";

    //     for(auto j : who[i])

    //         cout<<j<<" ";

    //     cout<<endl;

    // }

    // cout<<endl;

    // exit(0);

    int Max = -1;

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

        Max = max(Max, dp(topoSort[i]));

    return Max;

}



int main(){



    cin.tie(0);

    ios_base::sync_with_stdio(0);



    cin>>n>>m;



    while(m--){

        int a, b;

        cin>>a>>b;

        ady[a].push_back(b);

        who[b].push_back(a);

    }

    cout<<maxPath() - 1;

}

// Faster C++ solution for the same problem (measured speedup: 1.8153574615023889x):
#include<cstdio>

#include<math.h>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<set>

#include<map>

#include<queue>

using namespace std;

#define Case int t;scanf("%d", &t);while(t--)

typedef long long ll;

const int Max = 1e5 + 5;

const int INF = 0x3f3f3f3f;

const double PI = acos(-1.0);

int n, m;

int dp[Max];

int in[Max];

vector<int> G[Max];

queue<int> que;

int main(){

	cin >> n >> m;

	int u, v;

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

		cin >> u >> v;

		G[u].push_back(v);

		in[v]++;

	}



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

		if(!in[i]) que.push(i);

	}



	int ans = 0;

	while(!que.empty()){

		int now = que.front();

		que.pop();

		for(int i = 0; i < G[now].size(); i++){

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

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

			in[G[now][i]]--;

			if(!in[G[now][i]]) que.push(G[now][i]);

		}

	}



	cout << ans << endl;

}