| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| struct Edge { |
| int u, v; |
| }; |
|
|
| static vector<vector<int>> create_map(int N, int M, vector<int> A, vector<int> B) { |
| if (N == 1) { |
| return vector<vector<int>>(1, vector<int>(1, 1)); |
| } |
| |
| vector<vector<pair<int,int>>> adj(N); |
| vector<Edge> edges; |
| edges.reserve(M); |
| vector<int> deg(N,0); |
| for (int i = 0; i < M; ++i) { |
| int u = A[i]-1, v = B[i]-1; |
| edges.push_back({u,v}); |
| int id = (int)edges.size()-1; |
| adj[u].push_back({v,id}); |
| adj[v].push_back({u,id}); |
| deg[u]++; deg[v]++; |
| } |
| |
| |
| if (M == 0) { |
| |
| |
| |
| vector<vector<int>> C(1, vector<int>(1, 1)); |
| return C; |
| } |
| |
| vector<int> vis(N, 0); |
| vector<int> comp_id(N, -1); |
| int cid = 0; |
| for (int i = 0; i < N; ++i) if (!vis[i]) { |
| queue<int> q; q.push(i); vis[i]=1; comp_id[i]=cid; |
| while(!q.empty()){ |
| int u=q.front();q.pop(); |
| for(auto [v, id]: adj[u]){ |
| if(!vis[v]){vis[v]=1; comp_id[v]=cid; q.push(v);} |
| } |
| } |
| cid++; |
| } |
| |
| vector<int> comp_deg(cid,0); |
| for (auto &e: edges) { |
| comp_deg[comp_id[e.u]]++; |
| } |
| int best_comp = 0; |
| for (int i=1;i<cid;i++) if (comp_deg[i] > comp_deg[best_comp]) best_comp = i; |
| |
| vector<int> mapOldToNew(N, -1), mapNewToOld; |
| for (int i=0;i<N;i++) if (comp_id[i]==best_comp) { |
| mapOldToNew[i] = (int)mapNewToOld.size(); |
| mapNewToOld.push_back(i); |
| } |
| int nC = (int)mapNewToOld.size(); |
| vector<vector<pair<int,int>>> adjC(nC); |
| vector<Edge> edgesC; |
| edgesC.reserve(M); |
| vector<int> degC(nC,0); |
| for (auto &e: edges) { |
| if (comp_id[e.u]==best_comp) { |
| int u = mapOldToNew[e.u], v = mapOldToNew[e.v]; |
| int id = (int)edgesC.size(); |
| edgesC.push_back({u,v}); |
| adjC[u].push_back({v,id}); |
| adjC[v].push_back({u,id}); |
| degC[u]++; degC[v]++; |
| } |
| } |
| |
| vector<int> odd; |
| for (int i=0;i<nC;i++) if (degC[i]%2) odd.push_back(i); |
| auto bfs_path = [&](int s, int t)->vector<int>{ |
| vector<int> par(nC, -1), pareid(nC, -1); |
| queue<int> q; q.push(s); par[s] = s; |
| while(!q.empty()){ |
| int u=q.front();q.pop(); |
| if(u==t) break; |
| for(auto [v,id]: adjC[u]){ |
| if(par[v]==-1){ |
| par[v]=u; pareid[v]=id; q.push(v); |
| } |
| } |
| } |
| vector<int> path_eids; |
| if(par[t]==-1) return path_eids; |
| int cur=t; |
| while(cur!=s){ |
| path_eids.push_back(pareid[cur]); |
| cur=par[cur]; |
| } |
| reverse(path_eids.begin(), path_eids.end()); |
| return path_eids; |
| }; |
| vector<int> unmatched = odd; |
| vector<int> usedOdd(nC,0); |
| vector<char> paired(nC,0); |
| while (!unmatched.empty()) { |
| int s = unmatched.back(); unmatched.pop_back(); |
| if (paired[s]) continue; |
| |
| int best_t = -1; |
| vector<int> best_path; |
| for (int t : unmatched) if (!paired[t]) { |
| auto p = bfs_path(s, t); |
| if (p.empty()) continue; |
| if (best_t==-1 || p.size() < best_path.size()) { |
| best_t = t; |
| best_path = p; |
| } |
| } |
| if (best_t==-1) { |
| |
| if (!unmatched.empty()) { |
| best_t = unmatched.back(); unmatched.pop_back(); |
| |
| auto p = bfs_path(s, best_t); |
| if (p.empty()) { |
| |
| break; |
| } else best_path = p; |
| } else break; |
| } else { |
| |
| for (auto it = unmatched.begin(); it != unmatched.end(); ++it) { |
| if (*it == best_t) { unmatched.erase(it); break; } |
| } |
| } |
| |
| int cur = s; |
| for (int eid : best_path) { |
| int u = edgesC[eid].u, v = edgesC[eid].v; |
| |
| int id = (int)edgesC.size(); |
| edgesC.push_back({u,v}); |
| adjC[u].push_back({v,id}); |
| adjC[v].push_back({u,id}); |
| degC[u]++; degC[v]++; |
| } |
| paired[s]=paired[best_t]=1; |
| } |
| |
| int start = -1; |
| for (int i=0;i<nC;i++) if (!adjC[i].empty()) { start=i; break; } |
| if (start == -1) { |
| |
| vector<vector<int>> C(1, vector<int>(1, mapNewToOld.empty()?1:mapNewToOld[0]+1)); |
| return C; |
| } |
| int E2 = (int)edgesC.size(); |
| vector<char> used(E2, 0); |
| vector<int> itptr(nC, 0); |
| vector<vector<pair<int,int>>> adjIter = adjC; |
| vector<int> st; |
| vector<int> path; |
| st.push_back(start); |
| while(!st.empty()){ |
| int u = st.back(); |
| while(itptr[u] < (int)adjIter[u].size() && used[adjIter[u][itptr[u]].second]) itptr[u]++; |
| if (itptr[u] == (int)adjIter[u].size()) { |
| path.push_back(u); |
| st.pop_back(); |
| } else { |
| auto [v, id] = adjIter[u][itptr[u]]; |
| used[id] = 1; |
| st.push_back(v); |
| } |
| } |
| if ((int)path.size() < 2) { |
| |
| vector<vector<int>> C(1, vector<int>(1, mapNewToOld[start]+1)); |
| return C; |
| } |
| reverse(path.begin(), path.end()); |
| |
| vector<int> seq; |
| seq.reserve(path.size()); |
| for (int x : path) seq.push_back(mapNewToOld[x] + 1); |
| |
| if (!seq.empty() && seq.front() == seq.back()) seq.pop_back(); |
| int L = (int)seq.size(); |
| if (L <= 0) { |
| vector<vector<int>> C(1, vector<int>(1, mapNewToOld[start]+1)); |
| return C; |
| } |
| int K = min(L, 240); |
| |
| vector<vector<int>> C(K, vector<int>(K, 1)); |
| if (L <= 240) { |
| for (int r=0;r<K;r++){ |
| for (int c=0;c<K;c++){ |
| C[r][c] = seq[(r + c) % L]; |
| } |
| } |
| } else { |
| |
| for (int r=0;r<K;r++){ |
| for (int c=0;c<K;c++){ |
| C[r][c] = seq[(r + c) % L]; |
| } |
| } |
| } |
| return C; |
| } |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
| int T; |
| if (!(cin >> T)) { |
| return 0; |
| } |
| while (T--) { |
| int N, M; |
| cin >> N >> M; |
| vector<int> A(M), B(M); |
| for (int i = 0; i < M; ++i) { |
| cin >> A[i] >> B[i]; |
| } |
| vector<vector<int>> C = create_map(N, M, A, B); |
| int P = (int)C.size(); |
| cout << P << "\n"; |
| for (int i = 0; i < P; ++i) { |
| cout << (int)C[i].size() << (i+1<P?' ':'\n'); |
| } |
| cout << "\n"; |
| for (int i = 0; i < P; ++i) { |
| for (int j = 0; j < (int)C[i].size(); ++j) { |
| cout << C[i][j] << (j+1==(int)C[i].size()?'\n':' '); |
| } |
| } |
| cout.flush(); |
| } |
| return 0; |
| } |