#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\n'
#define pi pair<int,int>
#define adjs(name, type, size) vector<vector<type>>name(size)
#define adjpass(name, type) vector<vector<type>>&name
#define killua ios_base::sync_with_stdio(false), cin.tie(NULL), cout.tie(0)
int cases = 1;
int timer = 1;
set<pi > bridges;
void dfsSCC(int node, int dad, vector<int> &dfn, vector<int> &lowlink, adjpass(v, int)) {
dfn[node] = lowlink[node] = timer++;
for (auto i: v[node]) {
if (i == dad)
continue;
if (dfn[i] == -1) { //not vis
dfsSCC(i, node, dfn, lowlink, v);
lowlink[node] = min(lowlink[node], lowlink[i]);
if (lowlink[i] > dfn[node]) {
bridges.insert({min(node, i), max(node, i)});
}
} else {
lowlink[node] = min(lowlink[node], dfn[i]);
}
}
}
void dfs(int node, vector<set<int >> &v, vector<int> &vis, int &last, int &mx, int cur) {
vis[node] = 1;
if (cur > mx) {
mx = cur;
last = node;
} else if (cur == mx) {
last = min(last, node);
}
for (auto i: v[node]) {
if (!vis[i]) {
dfs(i, v, vis, last, mx, cur + 1);
}
}
}
class DSU {
private:
vector<int> rank, par, size;
public:
DSU(int n = 0) {
rank.resize(n + 1);
par.resize(n + 1);
size.resize(n + 1, 1);
for (int i = 0; i <= n; i++)
par[i] = i;
}
int findUpar(int node) {
if (node == par[node])
return node;
return par[node] = findUpar(par[node]);//path comp
}
void unionbyRank(int u, int v) {
int UparU = findUpar(u);
int UparV = findUpar(v);
if (UparU == UparV)
return;
if (rank[UparU] < rank[UparV]) {
par[UparU] = UparV;
} else {
par[UparV] = UparU;
rank[UparU] += (rank[UparU] == rank[UparV]);
}
}
void unionbySize(int u, int v) {
int UparU = findUpar(u);
int UparV = findUpar(v);
if (UparU == UparV)
return;
if (size[UparU] < size[UparV]) {
par[UparU] = UparV;
size[UparV] += size[UparU];
} else {
par[UparV] = UparU;
size[UparU] += size[UparV];
}
}
};
void gon() {
int n, m;
cin >> n >> m;
adjs(v, int, n + 5);
vector<pi > ed;
for (int i = 0; i < m; i++) {
int l, r;
cin >> l >> r;
ed.push_back({min(l, r), max(l, r)});
v[l].push_back(r);
v[r].push_back(l);
}
vector<int> dfn(n + 5, -1), lowlink(n + 5, -1);
timer = 1;
bridges.clear();
for (int i = 1; i <= n; i++) {
if (dfn[i] == -1) {
dfsSCC(i, -1, dfn, lowlink, v);
}
}
map<pi, int> mp;
for (auto i: bridges)
mp[i] = 1;
DSU d(n + 5);
for (auto i: ed) {
if (!mp.count(i)) {
d.unionbySize(i.first, i.second);
}
}
vector<int> comp(n + 5, 1e9);
for (int i = 1; i <= n; i++) {
comp[d.findUpar(i)] = min(comp[d.findUpar(i)], i);
}
vector<set<int >> mst(n + 5);
int cot = 0;
for (auto i: ed) {
if (!mp.count(i)) {
continue;
}
cot++;
int a = comp[d.findUpar(i.first)];
int b = comp[d.findUpar(i.second)];
mst[a].insert(b);
mst[b].insert(a);
}
int St = 1;
int last = 1;
int mx = 0;
int cur = 0;
vector<int> vis(n + 5);
dfs(St, mst, vis, last, mx, cur);
vis.assign(n + 5, 0);
int L = last;
St = last;
mx = 0;
cur = 0;
dfs(St, mst, vis, last, mx, cur);
cout << cot - mx << endl;
}
int32_t main() {
killua;
int t = 1;
if (cases) cin >> t;
while (t--) {
gon();
}
}
I2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CiNkZWZpbmUgaW50IGxvbmcgbG9uZwojZGVmaW5lIGVuZGwgJ1xuJwojZGVmaW5lIHBpIHBhaXI8aW50LGludD4KI2RlZmluZSBhZGpzKG5hbWUsIHR5cGUsIHNpemUpIHZlY3Rvcjx2ZWN0b3I8dHlwZT4+bmFtZShzaXplKQojZGVmaW5lIGFkanBhc3MobmFtZSwgdHlwZSkgdmVjdG9yPHZlY3Rvcjx0eXBlPj4mbmFtZQojZGVmaW5lIGtpbGx1YSBpb3NfYmFzZTo6c3luY193aXRoX3N0ZGlvKGZhbHNlKSwgY2luLnRpZShOVUxMKSwgY291dC50aWUoMCkKaW50IGNhc2VzID0gMTsKaW50IHRpbWVyID0gMTsKc2V0PHBpID4gYnJpZGdlczsKCnZvaWQgZGZzU0NDKGludCBub2RlLCBpbnQgZGFkLCB2ZWN0b3I8aW50PiAmZGZuLCB2ZWN0b3I8aW50PiAmbG93bGluaywgYWRqcGFzcyh2LCBpbnQpKSB7CiAgICBkZm5bbm9kZV0gPSBsb3dsaW5rW25vZGVdID0gdGltZXIrKzsKICAgIGZvciAoYXV0byBpOiB2W25vZGVdKSB7CiAgICAgICAgaWYgKGkgPT0gZGFkKQogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICBpZiAoZGZuW2ldID09IC0xKSB7IC8vbm90IHZpcwogICAgICAgICAgICBkZnNTQ0MoaSwgbm9kZSwgZGZuLCBsb3dsaW5rLCB2KTsKICAgICAgICAgICAgbG93bGlua1tub2RlXSA9IG1pbihsb3dsaW5rW25vZGVdLCBsb3dsaW5rW2ldKTsKICAgICAgICAgICAgaWYgKGxvd2xpbmtbaV0gPiBkZm5bbm9kZV0pIHsKICAgICAgICAgICAgICAgIGJyaWRnZXMuaW5zZXJ0KHttaW4obm9kZSwgaSksIG1heChub2RlLCBpKX0pOwogICAgICAgICAgICB9CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgbG93bGlua1tub2RlXSA9IG1pbihsb3dsaW5rW25vZGVdLCBkZm5baV0pOwogICAgICAgIH0KICAgIH0KfQoKdm9pZCBkZnMoaW50IG5vZGUsIHZlY3RvcjxzZXQ8aW50ID4+ICZ2LCB2ZWN0b3I8aW50PiAmdmlzLCBpbnQgJmxhc3QsIGludCAmbXgsIGludCBjdXIpIHsKICAgIHZpc1tub2RlXSA9IDE7CiAgICBpZiAoY3VyID4gbXgpIHsKICAgICAgICBteCA9IGN1cjsKICAgICAgICBsYXN0ID0gbm9kZTsKICAgIH0gZWxzZSBpZiAoY3VyID09IG14KSB7CiAgICAgICAgbGFzdCA9IG1pbihsYXN0LCBub2RlKTsKICAgIH0KICAgIGZvciAoYXV0byBpOiB2W25vZGVdKSB7CiAgICAgICAgaWYgKCF2aXNbaV0pIHsKICAgICAgICAgICAgZGZzKGksIHYsIHZpcywgbGFzdCwgbXgsIGN1ciArIDEpOwogICAgICAgIH0KICAgIH0KfQoKY2xhc3MgRFNVIHsKcHJpdmF0ZToKICAgIHZlY3RvcjxpbnQ+IHJhbmssIHBhciwgc2l6ZTsKcHVibGljOgogICAgRFNVKGludCBuID0gMCkgewogICAgICAgIHJhbmsucmVzaXplKG4gKyAxKTsKICAgICAgICBwYXIucmVzaXplKG4gKyAxKTsKICAgICAgICBzaXplLnJlc2l6ZShuICsgMSwgMSk7CiAgICAgICAgZm9yIChpbnQgaSA9IDA7IGkgPD0gbjsgaSsrKQogICAgICAgICAgICBwYXJbaV0gPSBpOwogICAgfQoKICAgIGludCBmaW5kVXBhcihpbnQgbm9kZSkgewogICAgICAgIGlmIChub2RlID09IHBhcltub2RlXSkKICAgICAgICAgICAgcmV0dXJuIG5vZGU7CiAgICAgICAgcmV0dXJuIHBhcltub2RlXSA9IGZpbmRVcGFyKHBhcltub2RlXSk7Ly9wYXRoIGNvbXAKICAgIH0KCiAgICB2b2lkIHVuaW9uYnlSYW5rKGludCB1LCBpbnQgdikgewogICAgICAgIGludCBVcGFyVSA9IGZpbmRVcGFyKHUpOwogICAgICAgIGludCBVcGFyViA9IGZpbmRVcGFyKHYpOwogICAgICAgIGlmIChVcGFyVSA9PSBVcGFyVikKICAgICAgICAgICAgcmV0dXJuOwogICAgICAgIGlmIChyYW5rW1VwYXJVXSA8IHJhbmtbVXBhclZdKSB7CiAgICAgICAgICAgIHBhcltVcGFyVV0gPSBVcGFyVjsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwYXJbVXBhclZdID0gVXBhclU7CiAgICAgICAgICAgIHJhbmtbVXBhclVdICs9IChyYW5rW1VwYXJVXSA9PSByYW5rW1VwYXJWXSk7CiAgICAgICAgfQogICAgfQoKICAgIHZvaWQgdW5pb25ieVNpemUoaW50IHUsIGludCB2KSB7CiAgICAgICAgaW50IFVwYXJVID0gZmluZFVwYXIodSk7CiAgICAgICAgaW50IFVwYXJWID0gZmluZFVwYXIodik7CiAgICAgICAgaWYgKFVwYXJVID09IFVwYXJWKQogICAgICAgICAgICByZXR1cm47CiAgICAgICAgaWYgKHNpemVbVXBhclVdIDwgc2l6ZVtVcGFyVl0pIHsKICAgICAgICAgICAgcGFyW1VwYXJVXSA9IFVwYXJWOwogICAgICAgICAgICBzaXplW1VwYXJWXSArPSBzaXplW1VwYXJVXTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwYXJbVXBhclZdID0gVXBhclU7CiAgICAgICAgICAgIHNpemVbVXBhclVdICs9IHNpemVbVXBhclZdOwogICAgICAgIH0KICAgIH0KfTsKCnZvaWQgZ29uKCkgewogICAgaW50IG4sIG07CiAgICBjaW4gPj4gbiA+PiBtOwogICAgYWRqcyh2LCBpbnQsIG4gKyA1KTsKICAgIHZlY3RvcjxwaSA+IGVkOwogICAgZm9yIChpbnQgaSA9IDA7IGkgPCBtOyBpKyspIHsKICAgICAgICBpbnQgbCwgcjsKICAgICAgICBjaW4gPj4gbCA+PiByOwogICAgICAgIGVkLnB1c2hfYmFjayh7bWluKGwsIHIpLCBtYXgobCwgcil9KTsKICAgICAgICB2W2xdLnB1c2hfYmFjayhyKTsKICAgICAgICB2W3JdLnB1c2hfYmFjayhsKTsKICAgIH0KCiAgICB2ZWN0b3I8aW50PiBkZm4obiArIDUsIC0xKSwgbG93bGluayhuICsgNSwgLTEpOwogICAgdGltZXIgPSAxOwogICAgYnJpZGdlcy5jbGVhcigpOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKSB7CiAgICAgICAgaWYgKGRmbltpXSA9PSAtMSkgewogICAgICAgICAgICBkZnNTQ0MoaSwgLTEsIGRmbiwgbG93bGluaywgdik7CiAgICAgICAgfQogICAgfQogICAgbWFwPHBpLCBpbnQ+IG1wOwogICAgZm9yIChhdXRvIGk6IGJyaWRnZXMpCiAgICAgICAgbXBbaV0gPSAxOwogICAgRFNVIGQobiArIDUpOwogICAgZm9yIChhdXRvIGk6IGVkKSB7CiAgICAgICAgaWYgKCFtcC5jb3VudChpKSkgewogICAgICAgICAgICBkLnVuaW9uYnlTaXplKGkuZmlyc3QsIGkuc2Vjb25kKTsKICAgICAgICB9CiAgICB9CiAgICB2ZWN0b3I8aW50PiBjb21wKG4gKyA1LCAxZTkpOwogICAgZm9yIChpbnQgaSA9IDE7IGkgPD0gbjsgaSsrKSB7CiAgICAgICAgY29tcFtkLmZpbmRVcGFyKGkpXSA9IG1pbihjb21wW2QuZmluZFVwYXIoaSldLCBpKTsKICAgIH0KICAgIHZlY3RvcjxzZXQ8aW50ID4+IG1zdChuICsgNSk7CiAgICBpbnQgY290ID0gMDsKICAgIGZvciAoYXV0byBpOiBlZCkgewogICAgICAgIGlmICghbXAuY291bnQoaSkpIHsKICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgfQogICAgICAgIGNvdCsrOwogICAgICAgIGludCBhID0gY29tcFtkLmZpbmRVcGFyKGkuZmlyc3QpXTsKICAgICAgICBpbnQgYiA9IGNvbXBbZC5maW5kVXBhcihpLnNlY29uZCldOwogICAgICAgIG1zdFthXS5pbnNlcnQoYik7CiAgICAgICAgbXN0W2JdLmluc2VydChhKTsKICAgIH0KICAgIGludCBTdCA9IDE7CiAgICBpbnQgbGFzdCA9IDE7CiAgICBpbnQgbXggPSAwOwogICAgaW50IGN1ciA9IDA7CiAgICB2ZWN0b3I8aW50PiB2aXMobiArIDUpOwogICAgZGZzKFN0LCBtc3QsIHZpcywgbGFzdCwgbXgsIGN1cik7CiAgICB2aXMuYXNzaWduKG4gKyA1LCAwKTsKICAgIGludCBMID0gbGFzdDsKICAgIFN0ID0gbGFzdDsKICAgIG14ID0gMDsKICAgIGN1ciA9IDA7CiAgICBkZnMoU3QsIG1zdCwgdmlzLCBsYXN0LCBteCwgY3VyKTsKICAgIGNvdXQgPDwgY290IC0gbXggPDwgZW5kbDsKfQoKaW50MzJfdCBtYWluKCkgewogICAga2lsbHVhOwogICAgaW50IHQgPSAxOwogICAgaWYgKGNhc2VzKSBjaW4gPj4gdDsKICAgIHdoaWxlICh0LS0pIHsKICAgICAgICBnb24oKTsKICAgIH0KfQ==