/*
Author: Ritik Patel
*/
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& STL DEBUGGER &&&&&&&&&&&&&&&&&&&&&&&&&&&
// #define _GLIBCXX_DEBUG // Iterator safety; out-of-bounds access for Containers, etc.
// #pragma GCC optimize "trapv" // abort() on (signed) integer overflow.
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& LIBRARIES &&&&&&&&&&&&&&&&&&&&&&&&&&&
#include <bits/stdc++.h>
using namespace std;
/*#include <ext/pb_ds/assoc_container.hpp> // Common file
#include <ext/pb_ds/tree_policy.hpp> // Including tree_order_statistics_node_update
template<typename T, typename V = __gnu_pbds::null_type>
using ordered_set = __gnu_pbds::tree<T, V, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
*/
//find_by_order()->returns an iterator to the k-th largest element(0-based indexing)
//order_of_key()->Number of items that are strictly smaller than our item
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& DEFINES &&&&&&&&&&&&&&&&&&&&&&&&&&&
#define int long long int
// #define ll long long int
#define all(i) i.begin(), i.end()
#define sz(a) (int)a.size()
// #define ld long double
// const ld PI = 3.141592;
const int dx4[4] = {0, 1, 0, -1};
const int dy4[4] = {-1, 0, 1, 0};
const int dx8[8] = {-1, -1, -1, 0, 1, 1, 1, 0};
const int dy8[8] = {-1, 0, 1, 1, 1, 0, -1, -1};
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& DEBUG &&&&&&&&&&&&&&&&&&&&&&&&&&&
#define XOX
vector<string> vec_splitter(string s) {
for(char& c: s) c = c == ','? ' ': c;
stringstream ss; ss << s;
vector<string> res;
for(string z; ss >> z; res.push_back(z));
return res;
}
void debug_out(vector<string> __attribute__ ((unused)) args, __attribute__ ((unused)) int idx) { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(vector<string> args, int idx, Head H, Tail... T) {
if(idx > 0) cerr << ", ";
stringstream ss; ss << H;
cerr << args[idx] << " = " << ss.str();
debug_out(args, idx + 1, T...);
}
#ifdef XOX
#define debug(...) debug_out(vec_splitter(#__VA_ARGS__), 0, __VA_ARGS__)
#else
#define debug(...) 42
#endif
//&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& CODE &&&&&&&&&&&&&&&&&&&&&&&&&&&
const int MAXN = 1e5 + 5;
const int MAXM = 1e5 + 5;
int N, M, timer, compid;
vector<pair<int, int>> g[MAXN];
bool used[MAXN], isBridge[MAXM];
int comp[MAXN], tin[MAXN], minAncestor[MAXN];
vector<int> tree[MAXN]; // Store 2-edge-connected component tree.(Bridge tree).
void dfs(int v, int p) {
tin[v] = minAncestor[v] = ++timer;
used[v] = 1;
for(auto &e: g[v]) {
int to, id;
tie(to, id) = e;
if(to == p) continue;
if(used[to]) {
minAncestor[v] = min(minAncestor[v], tin[to]);
} else {
dfs(to, v);
minAncestor[v] = min(minAncestor[v], minAncestor[to]);
if(minAncestor[to] > tin[v]) {
isBridge[id] = true;
}
}
}
}
void dfs1(int v, int p) {
used[v] = 1;
comp[v] = compid;
for(auto &e: g[v]) {
int to, id;
tie(to, id) = e;
if(isBridge[id]) { // avoid traversing from this edge. so we get full component.
continue;
}
if(used[to]) {
continue;
}
dfs1(to, v);
}
}
vector<pair<int, int>> edges;
void addEdge(int from, int to, int id) {
g[from].push_back({to, id});
g[to].push_back({from, id});
edges[id] = {from, to};
}
void initB() {
for(int i = 0; i <= compid; ++i)
tree[i].clear();
for(int i = 1; i <= N; ++i)
used[i] = false;
for(int i = 1; i <= M; ++i)
isBridge[i] = false;
timer = 0;
compid = 0;
}
void bridge_tree() {
initB();
dfs(1, -1); //Assuming graph is connected.
for(int i = 1; i <= N; ++i)
used[i] = 0;
for(int i = 1; i <= N; ++i) {
if(!used[i]) {
dfs1(i, -1);
++compid;
}
}
for(int i = 1; i <= M; ++i) {
if(isBridge[i]) {
int u, v;
tie(u, v) = edges[i];
// connect two componets using edge.
tree[comp[u]].push_back(comp[v]);
tree[comp[v]].push_back(comp[u]);
}
}
}
void init() {
edges.clear(); edges.resize(M + 1);
for(int i = 1; i <= N; ++i)
g[i].clear();
}
int farthest = -1, farthlvl = -1;
int totalEdges = 0;
void dfs2(int v, int p, int lvl = 0) {
int child = 1;
for(auto &to: tree[v]) {
if(to == p) continue;
++totalEdges;
++child; dfs2(to, v, lvl + 1);
}
// If leaf node.
if(child == 1 and lvl > farthlvl)
farthest = v, farthlvl = lvl;
}
int diameter = 0;
void dfs3(int v, int p, int lvl = 0) {
diameter = max(diameter, lvl);
for(auto &to: tree[v]) {
if(to == p) continue;
dfs3(to, v, lvl + 1);
}
}
void solve() {
cin >> N >> M;
init();
for(int i = 1; i <= M; ++i) {
int u, v;
cin >> u >> v; addEdge(u, v, i);
}
bridge_tree();
farthest = -1, farthlvl = -1;
totalEdges = 0, diameter = 0;
// Find diameter.
dfs2(0, -1);
dfs3(farthest, -1);
cout << totalEdges - diameter << '\n';
}
int32_t main(){
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
int T = 1;
cin >> T;
for(int i = 1; i <= T; ++i){
// cout << "Case #" << i << ": ";
solve();
}
return 0;
}
/*
Sample inp
*/
LyoKCUF1dGhvcjogUml0aWsgUGF0ZWwKKi8KIAogCi8vJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmIFNUTCBERUJVR0dFUiAmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYKIAovLyAjZGVmaW5lIF9HTElCQ1hYX0RFQlVHICAgICAgIC8vIEl0ZXJhdG9yIHNhZmV0eTsgb3V0LW9mLWJvdW5kcyBhY2Nlc3MgZm9yIENvbnRhaW5lcnMsIGV0Yy4KLy8gI3ByYWdtYSBHQ0Mgb3B0aW1pemUgInRyYXB2IiAvLyBhYm9ydCgpIG9uIChzaWduZWQpIGludGVnZXIgb3ZlcmZsb3cuCiAKLy8mJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYgTElCUkFSSUVTICYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJgogCiNpbmNsdWRlIDxiaXRzL3N0ZGMrKy5oPgp1c2luZyBuYW1lc3BhY2Ugc3RkOwogCi8qI2luY2x1ZGUgPGV4dC9wYl9kcy9hc3NvY19jb250YWluZXIuaHBwPiAvLyBDb21tb24gZmlsZQojaW5jbHVkZSA8ZXh0L3BiX2RzL3RyZWVfcG9saWN5LmhwcD4gLy8gSW5jbHVkaW5nIHRyZWVfb3JkZXJfc3RhdGlzdGljc19ub2RlX3VwZGF0ZQp0ZW1wbGF0ZTx0eXBlbmFtZSBULCB0eXBlbmFtZSBWID0gX19nbnVfcGJkczo6bnVsbF90eXBlPgp1c2luZyBvcmRlcmVkX3NldCA9IF9fZ251X3BiZHM6OnRyZWU8VCwgViwgbGVzczxUPiwgX19nbnVfcGJkczo6cmJfdHJlZV90YWcsIF9fZ251X3BiZHM6OnRyZWVfb3JkZXJfc3RhdGlzdGljc19ub2RlX3VwZGF0ZT47IAoqLwovL2ZpbmRfYnlfb3JkZXIoKS0+cmV0dXJucyBhbiBpdGVyYXRvciB0byB0aGUgay10aCBsYXJnZXN0IGVsZW1lbnQoMC1iYXNlZCBpbmRleGluZykKLy9vcmRlcl9vZl9rZXkoKS0+TnVtYmVyIG9mIGl0ZW1zIHRoYXQgYXJlIHN0cmljdGx5IHNtYWxsZXIgdGhhbiBvdXIgaXRlbQogCi8vJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmIERFRklORVMgJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmCiAKI2RlZmluZSBpbnQgbG9uZyBsb25nIGludAovLyAjZGVmaW5lIGxsIGxvbmcgbG9uZyBpbnQKI2RlZmluZSBhbGwoaSkgaS5iZWdpbigpLCBpLmVuZCgpCiNkZWZpbmUgc3ooYSkgKGludClhLnNpemUoKQogCi8vICNkZWZpbmUgbGQgbG9uZyBkb3VibGUKLy8gY29uc3QgbGQgUEkgID0gMy4xNDE1OTI7CmNvbnN0IGludCBkeDRbNF0gPSB7MCwgMSwgMCwgLTF9Owpjb25zdCBpbnQgZHk0WzRdID0gey0xLCAwLCAxLCAwfTsKY29uc3QgaW50IGR4OFs4XSA9IHstMSwgLTEsIC0xLCAwLCAxLCAxLCAxLCAwfTsKY29uc3QgaW50IGR5OFs4XSA9IHstMSwgMCwgMSwgMSwgMSwgMCwgLTEsIC0xfTsKIAovLyYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiBERUJVRyAmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYKIAojZGVmaW5lIFhPWAp2ZWN0b3I8c3RyaW5nPiB2ZWNfc3BsaXR0ZXIoc3RyaW5nIHMpIHsKICAgIGZvcihjaGFyJiBjOiBzKSBjID0gYyA9PSAnLCc/ICAnICc6IGM7CiAgICBzdHJpbmdzdHJlYW0gc3M7IHNzIDw8IHM7CiAgICB2ZWN0b3I8c3RyaW5nPiByZXM7CiAgICBmb3Ioc3RyaW5nIHo7IHNzID4+IHo7IHJlcy5wdXNoX2JhY2soeikpOwogICAgcmV0dXJuIHJlczsKfQogCnZvaWQgZGVidWdfb3V0KHZlY3RvcjxzdHJpbmc+IF9fYXR0cmlidXRlX18gKCh1bnVzZWQpKSBhcmdzLCBfX2F0dHJpYnV0ZV9fICgodW51c2VkKSkgaW50IGlkeCkgeyBjZXJyIDw8IGVuZGw7IH0KdGVtcGxhdGUgPHR5cGVuYW1lIEhlYWQsIHR5cGVuYW1lLi4uIFRhaWw+CnZvaWQgZGVidWdfb3V0KHZlY3RvcjxzdHJpbmc+IGFyZ3MsIGludCBpZHgsIEhlYWQgSCwgVGFpbC4uLiBUKSB7CiAgICBpZihpZHggPiAwKSBjZXJyIDw8ICIsICI7CiAgICBzdHJpbmdzdHJlYW0gc3M7IHNzIDw8IEg7CiAgICBjZXJyIDw8IGFyZ3NbaWR4XSA8PCAiID0gIiA8PCBzcy5zdHIoKTsKICAgIGRlYnVnX291dChhcmdzLCBpZHggKyAxLCBULi4uKTsKfQogCiNpZmRlZiBYT1gKI2RlZmluZSBkZWJ1ZyguLi4pIGRlYnVnX291dCh2ZWNfc3BsaXR0ZXIoI19fVkFfQVJHU19fKSwgMCwgX19WQV9BUkdTX18pCiNlbHNlCiNkZWZpbmUgZGVidWcoLi4uKSA0MgojZW5kaWYKIAogCi8vJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmIENPREUgJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmCgpjb25zdCBpbnQgTUFYTiA9IDFlNSArIDU7CmNvbnN0IGludCBNQVhNID0gMWU1ICsgNTsKCmludCBOLCBNLCB0aW1lciwgY29tcGlkOwoKdmVjdG9yPHBhaXI8aW50LCBpbnQ+PiBnW01BWE5dOwpib29sIHVzZWRbTUFYTl0sIGlzQnJpZGdlW01BWE1dOwppbnQgY29tcFtNQVhOXSwgdGluW01BWE5dLCBtaW5BbmNlc3RvcltNQVhOXTsKCnZlY3RvcjxpbnQ+IHRyZWVbTUFYTl07IC8vIFN0b3JlIDItZWRnZS1jb25uZWN0ZWQgY29tcG9uZW50IHRyZWUuKEJyaWRnZSB0cmVlKS4KCnZvaWQgZGZzKGludCB2LCBpbnQgcCkgewogICAgdGluW3ZdID0gbWluQW5jZXN0b3Jbdl0gPSArK3RpbWVyOwogICAgdXNlZFt2XSA9IDE7CiAgICBmb3IoYXV0byAmZTogZ1t2XSkgewogICAgICAgIGludCB0bywgaWQ7CiAgICAgICAgdGllKHRvLCBpZCkgPSBlOwogICAgICAgIGlmKHRvID09IHApIGNvbnRpbnVlOwogICAgICAgIGlmKHVzZWRbdG9dKSB7CiAgICAgICAgICAgIG1pbkFuY2VzdG9yW3ZdID0gbWluKG1pbkFuY2VzdG9yW3ZdLCB0aW5bdG9dKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBkZnModG8sIHYpOwogICAgICAgICAgICBtaW5BbmNlc3Rvclt2XSA9IG1pbihtaW5BbmNlc3Rvclt2XSwgbWluQW5jZXN0b3JbdG9dKTsKICAgICAgICAgICAgaWYobWluQW5jZXN0b3JbdG9dID4gdGluW3ZdKSB7CiAgICAgICAgICAgICAgICBpc0JyaWRnZVtpZF0gPSB0cnVlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfQp9Cgp2b2lkIGRmczEoaW50IHYsIGludCBwKSB7CiAgICB1c2VkW3ZdID0gMTsKICAgIGNvbXBbdl0gPSBjb21waWQ7CiAgICBmb3IoYXV0byAmZTogZ1t2XSkgewogICAgICAgIGludCB0bywgaWQ7CiAgICAgICAgdGllKHRvLCBpZCkgPSBlOwogICAgICAgIAogICAgICAgIGlmKGlzQnJpZGdlW2lkXSkgeyAvLyBhdm9pZCB0cmF2ZXJzaW5nIGZyb20gdGhpcyBlZGdlLiBzbyB3ZSBnZXQgZnVsbCBjb21wb25lbnQuCiAgICAgICAgICAgIGNvbnRpbnVlOwogICAgICAgIH0KICAgICAgICBpZih1c2VkW3RvXSkgewogICAgICAgICAgICBjb250aW51ZTsKICAgICAgICB9CiAgICAgICAgZGZzMSh0bywgdik7CiAgICB9Cn0KCnZlY3RvcjxwYWlyPGludCwgaW50Pj4gZWRnZXM7Cgp2b2lkIGFkZEVkZ2UoaW50IGZyb20sIGludCB0bywgaW50IGlkKSB7CiAgICBnW2Zyb21dLnB1c2hfYmFjayh7dG8sIGlkfSk7CiAgICBnW3RvXS5wdXNoX2JhY2soe2Zyb20sIGlkfSk7CiAgICBlZGdlc1tpZF0gPSB7ZnJvbSwgdG99Owp9Cgp2b2lkIGluaXRCKCkgewoKICAgIGZvcihpbnQgaSA9IDA7IGkgPD0gY29tcGlkOyArK2kpCiAgICAgICAgdHJlZVtpXS5jbGVhcigpOwogICAgZm9yKGludCBpID0gMTsgaSA8PSBOOyArK2kpCiAgICAgICAgdXNlZFtpXSA9IGZhbHNlOwogICAgZm9yKGludCBpID0gMTsgaSA8PSBNOyArK2kpCiAgICAgICAgaXNCcmlkZ2VbaV0gPSBmYWxzZTsKICAgIAogICAgdGltZXIgPSAwOwogICAgY29tcGlkID0gMDsKfQoKdm9pZCBicmlkZ2VfdHJlZSgpIHsKCiAgICBpbml0QigpOwogICAgCiAgICBkZnMoMSwgLTEpOyAvL0Fzc3VtaW5nIGdyYXBoIGlzIGNvbm5lY3RlZC4KCiAgICBmb3IoaW50IGkgPSAxOyBpIDw9IE47ICsraSkKICAgICAgICB1c2VkW2ldID0gMDsKCiAgICBmb3IoaW50IGkgPSAxOyBpIDw9IE47ICsraSkgewogICAgICAgIGlmKCF1c2VkW2ldKSB7CiAgICAgICAgICAgIGRmczEoaSwgLTEpOwogICAgICAgICAgICArK2NvbXBpZDsKICAgICAgICB9CiAgICB9CgogICAgZm9yKGludCBpID0gMTsgaSA8PSBNOyArK2kpIHsKICAgICAgICBpZihpc0JyaWRnZVtpXSkgewogICAgICAgICAgICBpbnQgdSwgdjsKICAgICAgICAgICAgdGllKHUsIHYpID0gZWRnZXNbaV07CiAgICAgICAgICAgIC8vIGNvbm5lY3QgdHdvIGNvbXBvbmV0cyB1c2luZyBlZGdlLgogICAgICAgICAgICB0cmVlW2NvbXBbdV1dLnB1c2hfYmFjayhjb21wW3ZdKTsKICAgICAgICAgICAgdHJlZVtjb21wW3ZdXS5wdXNoX2JhY2soY29tcFt1XSk7CiAgICAgICAgfQogICAgfQp9Cgp2b2lkIGluaXQoKSB7CiAgICBlZGdlcy5jbGVhcigpOyBlZGdlcy5yZXNpemUoTSArIDEpOwogICAgZm9yKGludCBpID0gMTsgaSA8PSBOOyArK2kpCiAgICAgICAgZ1tpXS5jbGVhcigpOwp9CgppbnQgZmFydGhlc3QgPSAtMSwgZmFydGhsdmwgPSAtMTsKaW50IHRvdGFsRWRnZXMgPSAwOwoKdm9pZCBkZnMyKGludCB2LCBpbnQgcCwgaW50IGx2bCA9IDApIHsKICAgIGludCBjaGlsZCA9IDE7CiAgICBmb3IoYXV0byAmdG86IHRyZWVbdl0pIHsKICAgICAgICBpZih0byA9PSBwKSBjb250aW51ZTsKICAgICAgICArK3RvdGFsRWRnZXM7CiAgICAgICAgKytjaGlsZDsgZGZzMih0bywgdiwgbHZsICsgMSk7CiAgICB9CiAgICAvLyBJZiBsZWFmIG5vZGUuCiAgICBpZihjaGlsZCA9PSAxIGFuZCBsdmwgPiBmYXJ0aGx2bCkKICAgICAgICBmYXJ0aGVzdCA9IHYsIGZhcnRobHZsID0gbHZsOwp9CgppbnQgZGlhbWV0ZXIgPSAwOwoKdm9pZCBkZnMzKGludCB2LCBpbnQgcCwgaW50IGx2bCA9IDApIHsKICAgIGRpYW1ldGVyID0gbWF4KGRpYW1ldGVyLCBsdmwpOwogICAgZm9yKGF1dG8gJnRvOiB0cmVlW3ZdKSB7CiAgICAgICAgaWYodG8gPT0gcCkgY29udGludWU7CiAgICAgICAgZGZzMyh0bywgdiwgbHZsICsgMSk7CiAgICB9Cn0KCnZvaWQgc29sdmUoKSB7CiAgICBjaW4gPj4gTiA+PiBNOwoKICAgIGluaXQoKTsKCiAgICBmb3IoaW50IGkgPSAxOyBpIDw9IE07ICsraSkgewogICAgICAgIGludCB1LCB2OwogICAgICAgIGNpbiA+PiB1ID4+IHY7IGFkZEVkZ2UodSwgdiwgaSk7CiAgICB9CgogICAgCiAgICBicmlkZ2VfdHJlZSgpOwoKICAgIGZhcnRoZXN0ID0gLTEsIGZhcnRobHZsID0gLTE7CiAgICB0b3RhbEVkZ2VzID0gMCwgZGlhbWV0ZXIgPSAwOwogICAgLy8gRmluZCBkaWFtZXRlci4KICAgIGRmczIoMCwgLTEpOwoKICAgIGRmczMoZmFydGhlc3QsIC0xKTsKCiAgICBjb3V0IDw8IHRvdGFsRWRnZXMgLSBkaWFtZXRlciA8PCAnXG4nOwoKCn0KCgoKCmludDMyX3QgbWFpbigpewogICAgLy8gZnJlb3BlbigiaW5wdXQudHh0IiwiciIsc3RkaW4pOwogICAgLy8gZnJlb3Blbigib3V0cHV0LnR4dCIsInciLHN0ZG91dCk7IAogICAgaW9zX2Jhc2U6OnN5bmNfd2l0aF9zdGRpbyhmYWxzZSk7Y2luLnRpZShudWxscHRyKTtjb3V0LnRpZShudWxscHRyKTsKICAgIGludCBUID0gMTsgCiAgICBjaW4gPj4gVDsKICAgIGZvcihpbnQgaSA9IDE7IGkgPD0gVDsgKytpKXsKICAgICAgICAvLyBjb3V0IDw8ICJDYXNlICMiIDw8IGkgPDwgIjogIjsKICAgICAgICBzb2x2ZSgpOwogICAgfQogICAgcmV0dXJuIDA7Cn0KIAovKgpTYW1wbGUgaW5wCiov