stablegradients/pie-gem5-bysrc huggingface dataset:
// Original C++ solution (slower):
#include<map>

#include<cmath>

#include<stack>

#include<queue>

#include<cstdio>

#include<vector>

#include<cstring>

#include<iostream>

#include<algorithm>

using namespace std;

typedef long long ll;

template<class Read>void in(Read &x){

    x=0;

    int f=0;

    char ch=getchar();

    while(ch<'0'||ch>'9'){

        f|=(ch=='-');

        ch=getchar();

    }

    while(ch>='0'&&ch<='9'){

        x=(x<<1)+(x<<3)+(ch^48);

        ch=getchar();

    }

    x=f?-x:x;

    return;

}

struct Node{

    int x;

    int y;

}a[100005];

int n,m,ans,du[100005],h[100005],f[100005];

vector<int>v[100005],k[100005];

stack<int>q;

int main(){

    in(n);in(m);

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

        in(a[i].x);in(a[i].y);

        v[a[i].x].push_back(a[i].y);

        k[a[i].y].push_back(a[i].x);

        du[a[i].y]++;

    }

    for(int i=1;i<=n;i++)if(du[i]==0)q.push(i),h[++h[0]]=i;

    while(!q.empty()){

        int l=q.top();

        q.pop();

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

            int u=v[l][i];

            du[u]--;

            f[u]=max(f[u],f[l]+1);

            if(du[u]==0){

                q.push(u);

                h[++h[0]]=u;

            }

        }

    }

    for(int i=1;i<=n;i++)ans=max(ans,f[i]);

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

	return 0;

}


// Optimized solution to the same problem (faster):
#include<map>

#include<cmath>

#include<stack>

#include<queue>

#include<cstdio>

#include<vector>

#include<cstring>

#include<iostream>

#include<algorithm>

using namespace std;

typedef long long ll;

template<class Read>void in(Read &x){

    x=0;

    int f=0;

    char ch=getchar();

    while(ch<'0'||ch>'9'){

        f|=(ch=='-');

        ch=getchar();

    }

    while(ch>='0'&&ch<='9'){

        x=(x<<1)+(x<<3)+(ch^48);

        ch=getchar();

    }

    x=f?-x:x;

    return;

}

struct Node{

    int to;

    int next;

}a[100005];

int n,m,top,ans,head[100005],ru[100005],b[100005],f[100005];

queue<int>q;

void add(int x,int y){

    a[++top].to=y;

    a[top].next=head[x];

    head[x]=top;

}

int main(){

    in(n);in(m);

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

        int x,y;

        in(x);in(y);

        add(x,y);

        ru[y]++;

    }

    for(int i=1;i<=n;i++)if(ru[i]==0)q.push(i),b[++b[0]]=i;

    while(!q.empty()){

        int x=q.front();

        q.pop();

        for(int i=head[x];i;i=a[i].next){

            int y=a[i].to;

            ru[y]--;

            if(ru[y]==0)q.push(y),b[++b[0]]=y;

        }

    }

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

        for(int j=head[b[i]];j;j=a[j].next){

            int k=a[j].to;

            f[k]=max(f[k],f[b[i]]+1);

        }

    }

    for(int i=1;i<=n;i++)ans=max(ans,f[i]);

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

    return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<map>

#include<cmath>

#include<stack>

#include<queue>

#include<cstdio>

#include<vector>

#include<cstring>

#include<iostream>

#include<algorithm>

using namespace std;

typedef long long ll;

template<class Read>void in(Read &x){

    x=0;

    int f=0;

    char ch=getchar();

    while(ch<'0'||ch>'9'){

        f|=(ch=='-');

        ch=getchar();

    }

    while(ch>='0'&&ch<='9'){

        x=(x<<1)+(x<<3)+(ch^48);

        ch=getchar();

    }

    x=f?-x:x;

    return;

}

struct Node{

    int x;

    int y;

}a[100005];

int n,m,ans,du[100005],h[100005],f[100005];

vector<int>v[100005],k[100005];

queue<int>q;

int main(){

    in(n);in(m);

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

        in(a[i].x);in(a[i].y);

        v[a[i].x].push_back(a[i].y);

        k[a[i].y].push_back(a[i].x);

        du[a[i].y]++;

    }

    for(int i=1;i<=n;i++)if(du[i]==0)q.push(i),h[++h[0]]=i;

    while(!q.empty()){

        int l=q.front();

        q.pop();

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

            int u=v[l][i];

            du[u]--;

            f[u]=max(f[u],f[l]+1);

            if(du[u]==0){

                q.push(u);

                h[++h[0]]=u;

            }

        }

    }

    for(int i=1;i<=n;i++)ans=max(ans,f[i]);

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

	return 0;

}


// Optimized solution to the same problem (faster):
#include<map>

#include<cmath>

#include<stack>

#include<queue>

#include<cstdio>

#include<vector>

#include<cstring>

#include<iostream>

#include<algorithm>

using namespace std;

typedef long long ll;

template<class Read>void in(Read &x){

    x=0;

    int f=0;

    char ch=getchar();

    while(ch<'0'||ch>'9'){

        f|=(ch=='-');

        ch=getchar();

    }

    while(ch>='0'&&ch<='9'){

        x=(x<<1)+(x<<3)+(ch^48);

        ch=getchar();

    }

    x=f?-x:x;

    return;

}

struct Node{

    int to;

    int next;

}a[100005];

int n,m,top,ans,head[100005],ru[100005],b[100005],f[100005];

queue<int>q;

void add(int x,int y){

    a[++top].to=y;

    a[top].next=head[x];

    head[x]=top;

}

int main(){

    in(n);in(m);

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

        int x,y;

        in(x);in(y);

        add(x,y);

        ru[y]++;

    }

    for(int i=1;i<=n;i++)if(ru[i]==0)q.push(i),b[++b[0]]=i;

    while(!q.empty()){

        int x=q.front();

        q.pop();

        for(int i=head[x];i;i=a[i].next){

            int y=a[i].to;

            ru[y]--;

            if(ru[y]==0)q.push(y),b[++b[0]]=y;

        }

    }

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

        for(int j=head[b[i]];j;j=a[j].next){

            int k=a[j].to;

            f[k]=max(f[k],f[b[i]]+1);

        }

    }

    for(int i=1;i<=n;i++)ans=max(ans,f[i]);

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

    return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#pragma GCC optimize("O3")

#include <bits/stdc++.h>

#define ll   long long

#define ld long double

#define endl '\n'

#define INF 10000000000000000

#define pll pair<ll,ll>

#define ff first

#define ss second



using namespace std;

const ll N = 200005;

const ll MOD = 998244353;

vector<ll> g[N];

bool use[N];

    ll n,m;

    ll in_degree[N];

ll bfs() {

    ll d[N]={0};

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

        d[i]=INF;

    }

    priority_queue<pll> q;

    ll mx = 0;

    q.push(make_pair(0,0));

    while(!q.empty()) {

        ll v = q.top().ss;

        ll dw = q.top().ff;

        q.pop();

        if(d[v]>dw) continue;

        if(d[v]>mx) mx=d[v];

        for(ll i =0;i<g[v].size();i++) {

                ll to =g[v][i];



                if(in_degree[to]>=0)

                in_degree[to]--;

             //   cout<<i<<" "<<to<<" "<<in_degree[to]<<endl;

                if(d[to]==INF || d[to]<=d[v]) {

                    d[to]=d[v]+1;

                  //  q.push({d[to],to});

                }

                if(in_degree[to]==0) {

                    in_degree[to]--;

                    q.push({d[to],to});

                }

        }

    }

    //for(ll i =0;i<=n;i++) {

   //     cout<<in_degree[i]<<" "<<d[i]<<endl;

   // }

    return mx-1;

}

int main()

{

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

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

    ios_base::sync_with_stdio(false);

    cin.tie(NULL);

    cout.tie(NULL);



    cin>>n>>m;

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

        ll u,v;

        cin>>u>>v;

        g[u].push_back(v);

        use[v]=1;

        ++in_degree[v];

    }

    in_degree[0]=-1;

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

        if(!use[i]) {g[0].push_back(i);  in_degree[i]++;}

    }

  //  cout<<endl;

    cout<<bfs();



}


// Optimized solution to the same problem (faster):
#pragma GCC optimize("O3")

#include <bits/stdc++.h>

#define ll   long long

#define ld long double

#define endl '\n'

#define INF 10000000000000000

#define pll pair<ll,ll>

#define ff first

#define ss second



using namespace std;

const ll N = 200005;

const ll MOD = 998244353;

vector<ll> g[N];

bool vis[N];

ll d[N];

ll in_degree[N];

void dfs(ll v) {

    vis[v]=1;

    for(ll i =0;i<g[v].size();i++) {

        ll to = g[v][i];

        d[to]=max(d[to],d[v]+1);

        in_degree[to]--;

        if(in_degree[to]==0)

            dfs(to);

    }

}

int main()

{

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

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

    ios_base::sync_with_stdio(false);

    cin.tie(NULL);

    cout.tie(NULL);

    ll n,m;

    cin>>n>>m;

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

        ll u,v;

        cin>>u>>v;

        g[u].push_back(v);

        ++in_degree[v];

    }

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

        if(!vis[i] && in_degree[i]==0) dfs(i);

    }

    ll ans =0;

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

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

    }

    cout<<ans;





}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

vector<int> dp(100100,-1),graph[100100];



int ans(int curr){

    if(dp[curr] != -1){

        return dp[curr];

    }

    int ret = 0;

    for(int i : graph[curr]){

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

    }

    dp[curr] = ret;

    return ret;

}



int main()

{

    int n,m,a,b;

    cin >> n >> m;

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

        cin >> a >> b;

        graph[a].push_back(b);

    }

    int ansi=0;

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

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

    }

    cout << ansi;

}

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

using namespace std;

int n,m,ans,indeg[100001],dp[100001];

vector<vector<int>> graph;



int main(){

	cin >> n >> m;

	graph.resize(n+1);

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

		int a,b;

		cin >> a >> b;

		graph[a].push_back(b);

		indeg[b] += 1;

	}

	queue<int> q;

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

		if(indeg[i] == 0){

			q.push(i);

		}

	}

	vector<int> order;

	while(q.size()){

		int a = q.front();

		q.pop();

		order.push_back(a);

		for(int i : graph[a]){

			indeg[i] -= 1;

			if(indeg[i] == 0){

				q.push(i);

			}

		}

	}

	for(int i : order){

		for(int j : graph[i]){

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

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

		}

	}

	cout << ans << endl;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include "bits/stdc++.h"

using namespace std;

 

int dp[100005];

bool visited[100005];

vector<int> adj[100005];

 

void visit(int vertex){

	visited[vertex] = 1;

	dp[vertex] = 0;

	for(int child:adj[vertex]){

		if(!visited[child]){

			visit(child);

		}

		dp[vertex] = max(dp[vertex] , 1 + dp[child]);

	}

}

 

int main(){

	int n,m;

	cin>>n>>m;

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

		int x,y;

		cin>>x>>y;

		adj[x].push_back(y);

	}

	

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

		if(!visited[i]){

			visit(i);

		}

	}

	

	int ans = 0;

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

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

	}

	

	cout<<ans;

	

}

// Optimized solution to the same problem (faster):


// Problem : G - Longest Path

// Contest : AtCoder - Educational DP Contest

// URL : https://atcoder.jp/contests/dp/tasks/dp_g

// Memory Limit : 1024 MB

// Time Limit : 2000 ms

// Powered by CP Editor (https://github.com/cpeditor/cpeditor)



//#pragma GCC optimize "trapv"//  WA to RE int!!

#include <bits/stdc++.h>

#define FOR(i,n) for(int i=0;i<n;i++)

#define FORR(i,n) for(int i=n;i>=0;i--)

#define pb push_back

#define vlli vector<int>

#define slli set<int>

#define mlli map<int,int>

#define int long long int 

#define test int tt1234; cin>>tt1234;while(tt1234--)

#define endl "\n"

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

#define rep(i, begin, end) for (__typeof(end) i = (begin) - ((begin) > (end)); i != (end) - ((begin) > (end)); i += 1 - 2 * ((begin) > (end)))

#define error(x) cerr << #x <<" is " << x << endl;

#define Error(a,b) cerr<<"( "<<#a<<" , "<<#b<<" ) = ( "<<(a)<<" , "<<(b)<<" )\n";

#define fast ios_base::sync_with_stdio(false);cin.tie(NULL);

#define fint fast;test

#define SI(a,n) int a[n];FOR(i,n) cin>>a[i];

#define input(a,n) int n;cin>>n; SI(a,n)

#define set(a,x) memset(a,x,sizeof(a))

#define L(x)	((x)<<1)

#define R(x)	(((x)<<1)+1)

#define ft first

#define se second

#define MOD 1000000007

using namespace std;

vector<vector<int>>adj;

vector<bool>vis;

vector<int>dp;

int dfs(int node)

{

	int ans=0;

	vis[node]=true;

	dp[node]=0;

	for(auto child:adj[node])

	{

		if(!vis[child])

		{

			dfs(child);

		}

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

	}

	return dp[node];

}

void solve(){

	int n,e;

	cin>>n>>e;

	adj.resize(n+1,vector<int>());

	vis.resize(n+1);

	dp.resize(n+1);

	FOR(i,e)

	{

		int u,v;

		cin>>u>>v;

		adj[u].pb(v);

	}

	int ans=0;

	rep(i,1,n+1)

	{

		if(!vis[i])

		{

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

		}

	}

	cout<<ans;

	return;	

}





int32_t main() {

    // fint{

    	fast;

    	solve();

    // }

    return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>



using namespace std;



const int maxn = 1e5 + 10;



vector<int> adj[maxn];

int dp[maxn];

int ans = -1;



int dfs(int u)

{

    if (dp[u] != -1)

        return dp[u];

    int ans = 0;

    for(auto elem : adj[u]){

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

    }

    return dp[u] = ans;

}



int main()

{

    int n, m, x, y;

    cin >> n >> m;

    memset(dp, -1, sizeof dp);

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

        cin >> x >> y;

        adj[x].push_back(y);

    }

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

        if (dp[i] == -1){

            dfs(i);

        }

    }

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

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

    }

    cout << ans;

    return 0;

}


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



using namespace std;

const int maxn = 1e5 + 5;

vector<int> adj[maxn];

int dp[maxn];



int dfs(int u){

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

    dp[u] = 0;

    for (auto v : adj[u]){

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

    }

    return dp[u];

}



int main()

{

    int n, m;

    cin >> n >> m;

    for (int i = 1; i <= n; i++) dp[i] = -1;

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

        int x, y;

        cin >> x >> y;

        adj[x].push_back(y);

    }

    int ans = 0;

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

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

    }

    cout << ans;

    return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

typedef long long int ll;

using namespace std;

const ll mod=1e9+7;

ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}



vector<ll>graph[100005];

vector<ll>deg(100005,0);

vector<ll>dp(100005,0);

queue<ll>q;



int main(){

    ios::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);

    ll n,m;

    cin>>n>>m;

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

        ll a,b;

        cin>>a>>b;

        graph[a].push_back(b);

        deg[b]++;

    }

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

        if(deg[i]==0){

            q.push(i);

        }

    }

    while(!q.empty()){

        ll tete=q.front();

        q.pop();

        vector<ll>::iterator it=graph[tete].begin();

        for(it;it!=graph[tete].end();it++){

            dp[*it]=max(dp[*it],dp[tete]+1);

            deg[*it]--;

            if(deg[*it]==0)q.push(*it);

        }

    }

    ll res=0;

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

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

    }

    cout<<res<<endl;

    return 0;

    }


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

typedef long long int ll;

typedef long double ld;

using namespace std;

const ll mod=1e9+7;

const ll inf = (ll)1e17;

const ld eps = 1e-12;

const ld PI = 3.14159265358979323846;

ll mul(ll a, ll b, ll m = mod) { return (ll)(a * b) % m;}

ll add(ll a, ll b, ll m = mod) { a += b; if(a >= m) a -= m; if(a < 0) a += m; return a;}

ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}

ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}



int n,m;

const int N=100005;

vector<int>graph[N];

int deg[100005];

int dp[100005];



int main(){

    ios::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);

    cin>>n>>m;

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

        int a,b;

        cin>>a>>b;

        deg[b]++;

        graph[a].push_back(b);

    }

    queue<int>q;

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

        if(deg[i]==0)q.push(i);

    }

    while(!q.empty()){

        int tete=q.front();

        q.pop();

        for(int i=0;i<graph[tete].size();i++){

            int qq=graph[tete][i];

            deg[qq]--;

            dp[qq]=max(dp[qq],dp[tete]+1);

            if(deg[qq]==0)q.push(qq);

        }

    }

    int res=0;

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

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

    }

    cout<<res<<endl;



    return 0;

    }


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

#define EQ(x, y) (abs(x - y) < EPS)

typedef long long ll;

using namespace std;



const int N = 1e5 + 1;

int dp[N];

int n, m;

vector<vector<int>> g; // directed



int dfs(int node){

	if (dp[node] != -1)

		return dp[node];

	dp[node] = 0;

	for (auto &x : g[node]){

		if (dp[x] != -1){

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

		}

		else {

			dp[node] = max(dp[node], 1 + dfs(x));

		}

	}

	return dp[node];

}



int main(){

	ios_base::sync_with_stdio(0);

	cin.tie(0);

	cout.tie(0);

	cout.precision(10);



	cin >> n >> m;

	g.resize(n + 1);

	for (int i = 0; i < m; ++i){ // from x to y

		int x, y;

		cin >> x >> y;

		g[x].push_back(y);

	}

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

	

	int mx = -1;

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

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

	}

	cout << mx << '\n';

	return 0;

}

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



using namespace std;



vector<vector<int>> g;

vector<int> dp;



void solve(int u) {

  if (dp[u] != -1)

    return;

  dp[u] = 0;

  for (auto v : g[u]) {

    solve(v);

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

  }

}



int main() {

  ios_base::sync_with_stdio(0);

  cin.tie(0);

  int n, m;

  cin >> n >> m;

  g.resize(n + 1);

  dp.resize(n + 1, -1);

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

    int a, b;

    cin >> a >> b;

    g[a].push_back(b);

  }

  g[0].resize(n);

  iota(g[0].begin(), g[0].end(), 1);

  solve(0);

  cout << dp[0] - 1 << '\n';

  return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

#define EQ(x, y) (abs(x - y) < EPS)

typedef long long ll;

using namespace std;



const int N = 1e5 + 1;

int dp[N];

int n, m;

vector<vector<int>> g; // directed



int dfs(int node){

	dp[node] = 0;

	for (auto &x : g[node]){

		if (dp[x] != -1){

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

		}

		else {

			dp[node] = max(dp[node], 1 + dfs(x));

		}

	}

	return dp[node];

}



int main(){

	ios_base::sync_with_stdio(0);

	cin.tie(0);

	cout.tie(0);

	cout.precision(10);



	cin >> n >> m;

	g.resize(n + 1);

	for (int i = 0; i < m; ++i){ // from x to y

		int x, y;

		cin >> x >> y;

		g[x].push_back(y);

	}

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

	

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

		g[0].push_back(i);

	cout << dfs(0) - 1 << '\n';

	return 0;

}


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



using namespace std;



vector<vector<int>> g;

vector<int> dp;



void solve(int u) {

  if (dp[u] != -1)

    return;

  dp[u] = 0;

  for (auto v : g[u]) {

    solve(v);

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

  }

}



int main() {

  ios_base::sync_with_stdio(0);

  cin.tie(0);

  int n, m;

  cin >> n >> m;

  g.resize(n + 1);

  dp.resize(n + 1, -1);

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

    int a, b;

    cin >> a >> b;

    g[a].push_back(b);

  }

  g[0].resize(n);

  iota(g[0].begin(), g[0].end(), 1);

  solve(0);

  cout << dp[0] - 1 << '\n';

  return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <algorithm>

#include <assert.h>

#include <cmath>

#include <iostream>

#include <iomanip>

#include <list>

#include <memory.h>

#include <stack>

#include <string>

#include <time.h>

#include <vector>



using namespace std;



const int N = 1e5 + 1;

vector<int> g[N];

bool vis[N];

int dp[N];



int main()

{

	ios_base::sync_with_stdio(false);

	cin.tie(nullptr);



#ifdef _DEBUG

	(void)freopen("in.txt", "r", stdin);

#endif



	int n, m;

	cin >> n >> m;

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

		int x, y;

		cin >> x >> y;

		g[x].push_back(y);

	}



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

		g[0].push_back(i);

	

	stack<int> st;

	st.push(0);



	while (!st.empty()) {

		int u = st.top();

		if (vis[u]) {

			st.pop();

			for (auto& v : g[u])

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

		}

		else {

			vis[u] = true;

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

				if (!vis[v]);

					st.push(v);

			}

		}

	}



	cout << dp[0] - 1 << '\n';



	return 0;

}

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



using namespace std;



vector<vector<int>> g;

vector<int> dp;



void solve(int u) {

  if (dp[u] != -1)

    return;

  dp[u] = 0;

  for (auto v : g[u]) {

    solve(v);

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

  }

}



int main() {

  ios_base::sync_with_stdio(0);

  cin.tie(0);

  int n, m;

  cin >> n >> m;

  g.resize(n + 1);

  dp.resize(n + 1, -1);

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

    int a, b;

    cin >> a >> b;

    g[a].push_back(b);

  }

  g[0].resize(n);

  iota(g[0].begin(), g[0].end(), 1);

  solve(0);

  cout << dp[0] - 1 << '\n';

  return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

const int N=1e5+5;

int dp[N],ans=-1;

int n,m,x[N],y[N];

vector<int>vf[N],vb[N],e,v[N];

bool f[N];

int dfs(int now)

{

	if(dp[now]==-1){

		if(v[now].empty())

		{

			dp[now]=0;

			return dp[now];

		}

		int res=-1;

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

			res=max(res,dfs(v[now][i])+1);

		dp[now]=res;

		return res;

	}

	else

		return dp[now];

}

int main()

{

	std::ios::sync_with_stdio(false);

	cin>>n>>m;

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

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

	{

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

		v[x[i]].push_back(y[i]);

		f[y[i]]=true;

	}

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

		if(!f[i])

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

	cout<<ans<<endl;

	return 0;

}

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

using namespace std;

const int N=1e5+5;

queue<int>q;

int deg[N],n,m,ans,dist[N];

vector<int>v[N];

int main()

{

	cin>>n>>m;

	while(m--)

	{

		int a,b;

		cin>>a>>b;

		a--,b--;

		v[a].push_back(b);

		deg[b]++;

	}

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

		if(!deg[i])

			q.push(i);

	while(!q.empty())

	{

		int now=q.front();q.pop();

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

		{

			int to=v[now][i];

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

			ans=max(ans,dist[to]);

			deg[to]--;

			if(!deg[to])q.push(to);

		}

	}

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

#define pb push_back

using namespace std;

const int N=1e5+5;

int n,m,dp[N],in[N],ans=-1;

vector<int>v[N];

bool notroot[N];

int dfs(int now)

{

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

	if(v[now].empty())return 0;

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

	{

		int to=v[now][i];

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

	}

	return dp[now];

}

int main()

{

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

	cin>>n>>m;

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

	{

		int a,b;

		cin>>a>>b;

		a--,b--;

		v[a].pb(b);

		notroot[b]=true;

	}

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

		if(!notroot[i])

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

	cout<<ans<<endl; 

	return 0;

}

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

using namespace std;

const int N=1e5+5;

queue<int>q;

int deg[N],n,m,ans,dist[N];

vector<int>v[N];

int main()

{

	cin>>n>>m;

	while(m--)

	{

		int a,b;

		cin>>a>>b;

		a--,b--;

		v[a].push_back(b);

		deg[b]++;

	}

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

		if(!deg[i])

			q.push(i);

	while(!q.empty())

	{

		int now=q.front();q.pop();

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

		{

			int to=v[now][i];

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

			ans=max(ans,dist[to]);

			deg[to]--;

			if(!deg[to])q.push(to);

		}

	}

	cout<<ans<<endl;

	return 0;

}

// Fastest known solution for this problem: