#include <bits/stdc++.h> using namespace std; #define ll long long #define ull unsigned long long #define ld long double #define pb push_back #define ppb pop_back #define pii pair<ll, ll> #define pll pair<ll, ll> #define vi vector<ll> #define vll vector<ll> #define vull vector<ull> #define vpii vector<pll > #define vpll vector<pll > #define mp make_pair #define mt make_tuple #define ff first #define ss second #define uset unordered_set #define umap unordered_map #define all(x) x.begin(), x.end() #define revall(x) x.rbegin(), x.rend() #define rep(i, j, k) for(ll i = j; i < k; ++i) #define fastio ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); #define T int tt; cin>>tt; while(tt--) const ll MOD = (ll)(1e9+7); const int inf = (int)INFINITY; const ll INF = (ll)INFINITY; const int MAX = (int)(1e5+1); vector<int> par, dsu_2ecc, dsu_cc, dsu_cc_size; int bridges; int lca_iteration; vector<int> last_visit; void init(int n) { par.resize(n); dsu_2ecc.resize(n); dsu_cc.resize(n); dsu_cc_size.resize(n); lca_iteration = 0; last_visit.assign(n, 0); for (int i=0; i<n; ++i) { dsu_2ecc[i] = i; dsu_cc[i] = i; dsu_cc_size[i] = 1; par[i] = -1; } bridges = 0; } int find_2ecc(int v) { if (v == -1) return -1; return dsu_2ecc[v] == v ? v : dsu_2ecc[v] = find_2ecc(dsu_2ecc[v]); } int find_cc(int v) { v = find_2ecc(v); return dsu_cc[v] == v ? v : dsu_cc[v] = find_cc(dsu_cc[v]); } void make_root(int v) { v = find_2ecc(v); int root = v; int child = -1; while (v != -1) { int p = find_2ecc(par[v]); par[v] = child; dsu_cc[v] = root; child = v; v = p; } dsu_cc_size[root] = dsu_cc_size[child]; } void merge_path (int a, int b) { ++lca_iteration; vector<int> path_a, path_b; int lca = -1; while (lca == -1) { if (a != -1) { a = find_2ecc(a); path_a.push_back(a); if (last_visit[a] == lca_iteration) lca = a; last_visit[a] = lca_iteration; a = par[a]; } if (b != -1) { path_b.push_back(b); b = find_2ecc(b); if (last_visit[b] == lca_iteration) lca = b; last_visit[b] = lca_iteration; b = par[b]; } } for (int v : path_a) { dsu_2ecc[v] = lca; if (v == lca) break; --bridges; } for (int v : path_b) { dsu_2ecc[v] = lca; if (v == lca) break; --bridges; } } void add_edge(int a, int b) { a = find_2ecc(a); b = find_2ecc(b); if (a == b) return; int ca = find_cc(a); int cb = find_cc(b); if (ca != cb) { ++bridges; if (dsu_cc_size[ca] > dsu_cc_size[cb]) { swap(a, b); swap(ca, cb); } make_root(a); par[a] = dsu_cc[a] = b; dsu_cc_size[cb] += dsu_cc_size[a]; } else { merge_path(a, b); } } int main() { fastio; T { int n, m; cin >> n >> m; init(n); rep(i, 0, m) { int u, v; cin >> u >> v; add_edge(u, v); cout << bridges << '\n'; } } return 0; }