#include <iostream>
#include <queue>
#include <vector>
#include <cstring>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
vector<vector<int> > graph(n + 1);
int v1, v2;
int* degree = new int[n + 1];
memset(degree, 0, (n + 1) * sizeof(int));
for (int i = 0; i < m; i++) {
cin >> v1 >> v2;
graph[v1].push_back(v2);
graph[v2].push_back(v1);
degree[v1]++;
degree[v2]++;
}
int* dest = new int[n + 1];
int* vis = new int[n + 1];
memset(dest, 0xFF, (n + 1) * sizeof(int));
memset(vis, 0, (n + 1) * sizeof(int));
queue<int> q;
for (int i = 1; i < n + 1; i++) {
if (degree[i] == 1) {
q.push(i);
dest[i] = 1;
}
}
// while (!q.empty()) {
// int v = q.front();
// q.pop();
// vis[v] = 1;
// if (degree[v] == 0) dest[v]--;之前没有加这一步判定会导致结果可能大1
// for (vector<int>::iterator it = graph[v].begin(); it != graph[v].end(); it++) {
// degree[*it]--;
// if (!vis[*it] && degree[*it] == 1) {
// q.push(*it);
// dest[*it] = dest[v] + 1;
// }
// }
// }
// int maxVal = 0;
// for (int i = 1; i < n + 1; i++) {
// maxVal = max(maxVal, dest[i]);
// }
// cout << maxVal << endl;
//更直观的写法
int ans = 0;
while (!q.empty()) {
int sz = q.size();
bool removed = false;
for (int i = 0; i < sz; i++) {
int v = q.front();
q.pop();
if (degree[v] == 0) continue;
degree[v] = 0;
removed = true;
for (vector<int>::iterator it = graph[v].begin(); it != graph[v].end(); it++) {
degree[*it]--;
if (degree[*it] == 1) q.push(*it);
}
}
ans += removed ? 1 : 0;
}
cout << ans << endl;
}