#include <stdio.h>
#include <algorithm>
#include <vector>

using namespace std;

#define MAX_N 100010

#define eps 1e-7

int n, m, sol;

int use[MAX_N], out[MAX_N];

double depth[MAX_N];

vector <int> G[MAX_N];

inline bool cmp(int x, int y) {
	return depth[x] < depth[y];
}

void solve() { //adaug nodurile pe rand in DAG
	for (int i = 1; i <= n; i++) {
    	vector <int> v; //vecinii nodului i
		v.clear();

		for (vector <int>::iterator it = G[i].begin(); it != G[i].end(); ++it)
			if (use[*it])
				v.push_back(*it);

		sort(v.begin(), v.end(), cmp);

		if (v.size() > 0) {
			int len = v.size();

			if (len <= sol) {
				depth[i] = depth[v[0]] - 1;
            	out[i] = len;
			}
			else {
            	//las sa domine sol vecini

				depth[i] = n + 1;

				for (int j = len - 1; j >= len - sol; j--)
					depth[i] = min(depth[i], depth[v[j]] - eps);
				out[i] = sol;

				//o sa fie dominat de restul de vecini

				for (int j = len - sol - 1; j >= 0; j--) {
					out[v[j]]++;
                	sol = max(sol, out[v[j]]);
				}
			}
		}

		use[i] = 1;
	}

	printf("%d\n", sol);
}

int main() {

	freopen("dag.in", "r", stdin);
	freopen("dag.out", "w", stdout);
	
	scanf("%d %d", &n, &m);
	
	for (int i = 1; i <= m; i++) {
		int x, y;
		scanf("%d %d", &x, &y);

		G[x].push_back(y);
		G[y].push_back(x);
	}

	solve();

	return 0;
}
