#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
#define int long long
const int N = 5e5 + 5;
int head[N], cntt = 0;
struct Edge {
int to, next, val;
} edge[2 * N];
void add(int u, int v, int x) {
edge[++cntt].to = v;
edge[cntt].val = x;
edge[cntt].next = head[u];
head[u] = cntt;
}
int low[N], dfn[N];
int Tm;
set<pair<int, int>>ans; //ans储存所有割边
void tarjan(int x, int lst) { //注意cntt从1开始
int cnt = 0;
dfn[x] = low[x] = ++Tm;
for (int i = head[x]; i; i = edge[i].next) {
int y = edge[i].to;
if (i == (lst ^ 1))
continue; //判重边
if (!dfn[y]) {
tarjan(y, i);
low[x] = min(low[x], low[y]);
if (low[y] > dfn[x]) { // 割边判定条件
ans.emplace(min(x, y), max(x, y));
}
} else
low[x] = min(low[x], dfn[y]);
}
}
void solve() {
while (1) {
int n, m;
cin >> n >> m;
if (n == 0)
return;
cntt = 1, Tm = 0;
ans.clear();
for (int i = 1; i <= n; i++) {
dfn[i] = 0;
low[i] = 0;
head[i] = 0;
}
for (int i = 1; i <= m; i++) {
int u, v;
cin >> u >> v;
add(u, v, 1);
add(v, u, 1);
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
tarjan(i, 0);
cout << ans.size() << endl;
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T = 1;
//cin>>T;
while (T--) {
solve();
}
return 0;
}