#include using namespace std; static vector> create_map(int N, int M, vector A, vector B) { if (N == 1) return vector>(1, vector(1, 1)); vector> g(N + 1); vector> adj(N + 1, vector(N + 1, 0)); for (int i = 0; i < M; i++) { int u = A[i], v = B[i]; g[u].push_back(v); g[v].push_back(u); adj[u][v] = adj[v][u] = 1; } auto bfs_dist = [&](int s) { const int INF = 1e9; vector dist(N + 1, INF); queue q; dist[s] = 0; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int v : g[u]) if (dist[v] == INF) { dist[v] = dist[u] + 1; q.push(v); } } return dist; }; int root = 1; { int bestEcc = INT_MAX; for (int s = 1; s <= N; s++) { auto dist = bfs_dist(s); int ecc = 0; for (int v = 1; v <= N; v++) ecc = max(ecc, dist[v]); if (ecc < bestEcc) { bestEcc = ecc; root = s; } } } vector parent(N + 1, -1), depth(N + 1, 0); queue q; parent[root] = 0; depth[root] = 0; q.push(root); while (!q.empty()) { int u = q.front(); q.pop(); for (int v : g[u]) if (parent[v] == -1) { parent[v] = u; depth[v] = depth[u] + 1; q.push(v); } } // Build children lists (spanning tree) vector> children(N + 1); for (int v = 1; v <= N; v++) if (v != root) { if (parent[v] <= 0) { // Should not happen if a map exists and N>1, but keep safe. parent[v] = root; depth[v] = depth[root] + 1; } children[parent[v]].push_back(v); } int maxDepth = 0; for (int v = 1; v <= N; v++) maxDepth = max(maxDepth, depth[v]); // Assign patches for non-tree edges vector> patches(N + 1); for (int i = 0; i < M; i++) { int a = A[i], b = B[i]; if (parent[a] == b || parent[b] == a) continue; // tree edge already realized int u = a, v = b; if (depth[u] > depth[v]) swap(u, v); else if (depth[u] == depth[v] && u > v) swap(u, v); patches[u].push_back(v); } auto compute_heights = [&](int K, vector& height_out) -> bool { height_out.assign(N + 1, 0); vector patchCols(N + 1, 1), patchHeight(N + 1, 0); for (int u = 1; u <= N; u++) { int wrect = K - 2 * depth[u]; if (wrect < 1) return false; if ((!children[u].empty() || !patches[u].empty()) && wrect < 3) return false; if (!patches[u].empty() && wrect < 5) return false; int innerW = max(0, wrect - 2); int cols = 1; if (innerW >= 3) cols = max(1, innerW / 3); patchCols[u] = cols; int p = (int)patches[u].size(); int rows = (p + cols - 1) / cols; patchHeight[u] = 3 * rows; } vector order(N); iota(order.begin(), order.end(), 1); stable_sort(order.begin(), order.end(), [&](int x, int y) { if (depth[x] != depth[y]) return depth[x] > depth[y]; return x < y; }); for (int u : order) { long long childSum = 0; for (int ch : children[u]) childSum += height_out[ch]; long long childSep = (children[u].empty() ? 0LL : (long long)children[u].size() - 1); long long sepBetween = (!patches[u].empty() && !children[u].empty()) ? 1LL : 0LL; long long content = (long long)patchHeight[u] + sepBetween + childSum + childSep; long long h = max(2LL, 2LL + content); if (h > 1000000) return false; // paranoia height_out[u] = (int)h; } if (height_out[root] > K) return false; return true; }; auto feasible = [&](int K) -> bool { if (K < 1 || K > 240) return false; vector h; if (!compute_heights(K, h)) return false; // Also ensure we can nest widths down to maxDepth for nodes with nontrivial content. for (int u = 1; u <= N; u++) { int wrect = K - 2 * depth[u]; if (wrect < 1) return false; if ((!children[u].empty() || !patches[u].empty()) && wrect < 3) return false; if (!patches[u].empty() && wrect < 5) return false; } return true; }; int lo = 1, hi = 240, bestK = 240; while (lo <= hi) { int mid = (lo + hi) / 2; if (feasible(mid)) { bestK = mid; hi = mid - 1; } else { lo = mid + 1; } } int K = bestK; vector height; bool ok = compute_heights(K, height); if (!ok) { K = 240; compute_heights(K, height); } // Sort children for deterministic layout for (int u = 1; u <= N; u++) sort(children[u].begin(), children[u].end()); for (int u = 1; u <= N; u++) { // Keep patches deterministic sort(patches[u].begin(), patches[u].end()); } vector> C(K, vector(K, root)); struct Rect { int top, left, bottom, right; }; function layout = [&](int u, Rect r) { for (int i = r.top; i <= r.bottom; i++) { for (int j = r.left; j <= r.right; j++) C[i][j] = u; } int wrect = r.right - r.left + 1; int innerW = wrect - 2; int cols = 1; if (innerW >= 3) cols = max(1, innerW / 3); int p = (int)patches[u].size(); int rows = (p + cols - 1) / cols; int pH = 3 * rows; int row = r.top + 1; int col0 = r.left + 1; // Place patches as 3x3 blocks with center = v, surrounded by u. for (int idx = 0; idx < p; idx++) { int br = idx / cols; int bc = idx % cols; int baseR = row + 3 * br; int baseC = col0 + 3 * bc; int centerR = baseR + 1; int centerC = baseC + 1; if (centerR >= r.top + 1 && centerR <= r.bottom - 1 && centerC >= r.left + 1 && centerC <= r.right - 1) { C[centerR][centerC] = patches[u][idx]; } } row += pH; if (p > 0 && !children[u].empty()) row += 1; for (int i = 0; i < (int)children[u].size(); i++) { int ch = children[u][i]; int hch = height[ch]; Rect cr{row, r.left + 1, row + hch - 1, r.right - 1}; layout(ch, cr); row = cr.bottom + 1; if (i + 1 < (int)children[u].size()) row += 1; // separator row in color u } }; layout(root, Rect{0, 0, K - 1, K - 1}); auto validate = [&]() -> bool { vector cnt(N + 1, 0); static bool seen[41][41]; for (int i = 1; i <= N; i++) for (int j = 1; j <= N; j++) seen[i][j] = false; for (int i = 0; i < K; i++) { for (int j = 0; j < K; j++) { int c = C[i][j]; if (c < 1 || c > N) return false; cnt[c]++; if (i + 1 < K) { int d = C[i + 1][j]; if (c != d) { if (!adj[c][d]) return false; int x = min(c, d), y = max(c, d); seen[x][y] = true; } } if (j + 1 < K) { int d = C[i][j + 1]; if (c != d) { if (!adj[c][d]) return false; int x = min(c, d), y = max(c, d); seen[x][y] = true; } } } } for (int c = 1; c <= N; c++) if (cnt[c] == 0) return false; for (int i = 0; i < M; i++) { int u = A[i], v = B[i]; if (!seen[u][v]) return false; } return true; }; if (!validate()) { // Fallback: use maximum K and re-layout (should not happen). K = 240; compute_heights(K, height); C.assign(K, vector(K, root)); layout(root, Rect{0, 0, K - 1, K - 1}); // No further fallback. } return C; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int T; if (!(cin >> T)) return 0; for (int tc = 0; tc < T; tc++) { int N, M; cin >> N >> M; vector A(M), B(M); for (int i = 0; i < M; i++) cin >> A[i] >> B[i]; auto C = create_map(N, M, A, B); int K = (int)C.size(); cout << K << "\n"; for (int i = 0; i < K; i++) { if (i) cout << ' '; cout << (int)C[i].size(); } cout << "\n\n"; for (int i = 0; i < K; i++) { for (int j = 0; j < K; j++) { if (j) cout << ' '; cout << C[i][j]; } cout << "\n"; } if (tc + 1 < T) cout << "\n"; } return 0; }