/*
TASK: post
LANG: C
*/

#include <stdio.h>
#include <string.h>


#define MAXN 1010
#define MAXM 50010


typedef struct Vex TVex;
typedef struct Edge TEdge;


struct Vex
{
    int c, v;
    TEdge *edges;
	TEdge *rev;
};

struct Edge
{
    int v;
    TEdge *next;
};


int n, m;
TVex vs[MAXN];

int ec;
TEdge edges[3*MAXN];

int sp;
int stack[MAXN];

int edge_added[MAXN][MAXN];
TVex ss[MAXN];

int c;
int cc[MAXN];
int top;
int t[MAXN];
int f[MAXN][MAXN];


void add_edge(TVex vs[], int a, int b)
{
    TEdge *e = edges + ec++;
    e->v = b;
    e->next = vs[a].edges;
    vs[a].edges = e;
}


void add_rev_edge(TVex vs[], int a, int b)
{
    TEdge *e = edges + ec++;
    e->v = b;
    e->next = vs[a].rev;
    vs[a].rev = e;
}


void dfs(int v)
{
	vs[v].v = 1;
	
	TEdge *e;
	for (e = vs[v].edges; e; e = e->next)
	{
		if (vs[e->v].v == 0)
		{
			dfs(e->v);
		}
	}
	
	stack[sp++] = v;
}


void set_visited(int v)
{
	int i;
	for (i = 0; i < n; i++)
	{
		vs[i].v = v;
	}
}


void dfs2(int v, int c)
{
	vs[v].v = 1;
	vs[v].c = c;
	cc[c]++;
	
	TEdge *e;
	for (e = vs[v].rev; e; e = e->next)
	{
		if (vs[e->v].v == 0)
		{
			dfs2(e->v, c);
		}
	}
}


void dfs3(int v)
{
	ss[v].v = 1;
	
	TEdge *e;
	for (e = ss[v].edges; e; e = e->next)
	{
		if (ss[e->v].v == 0)
		{
			dfs3(e->v);
		}
	}
	
	t[v] = top++;
}


int getf(int x, int y)
{
	if (t[x] < t[y])
	{
		x ^= y ^= x ^= y;
	}
	
	if (f[x][y] == -1)
	{
		TEdge *e;
		for (e = ss[x].edges; e; e = e->next)
		{
			int t = getf(y, e->v);
			if (x != y)
			{
				t += cc[x];
			}
			
			if (t > f[x][y])
			{
				f[x][y] = t;
			}
		}
	}
	
	return f[x][y];
}


int main()
{
    scanf("%d%d", &n, &m);
    
    int i, j;
    for (i = 0; i < m; i++)
    {
		int a, b;
		scanf("%d%d", &a, &b);
		add_edge(vs, a - 1, b - 1);
		add_rev_edge(vs, b - 1, a - 1);
    }
    
    for (i = 0; i < n; i++)
    {
		if (vs[i].v == 0)
		{
			dfs(i);
		}
    }
	
	set_visited(0);
	
	while (sp-- > 0)
	{
		int v = stack[sp];
		if (vs[v].v == 0)
		{
			dfs2(v, c++);
		}
	}
	
	TEdge *e;
	for (i = 0; i < n; i++)
	{
		for (e = vs[i].edges; e; e = e->next)
		{
			int c1 = vs[i].c;
			int c2 = vs[e->v].c;
			if (c1 != c2 && !edge_added[c1][c2])
			{
				add_edge(ss, c2, c1);
				edge_added[c1][c2] = 1;
			}
		}
	}
	
	for (i = 0; i < c; i++)
	{
		if (ss[i].v == 0)
		{
			dfs3(i);
		}
	}
	
	memset(f, -1, sizeof(f));
	f[0][0] = cc[0];
	
	int ans = 0;
	for (i = 0; i < c; i++)
	{
		for (j = 0; j < c; j++)
		{
			int t = getf(i, j);
			if (t > ans)
			{
				ans = t;
			}
		}
	}
	
	printf("%d\n", ans);
    
    return 0;
}
