| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| 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<int>> g(N + 1); |
| vector<vector<char>> adj(N + 1, vector<char>(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<int> dist(N + 1, INF); |
| queue<int> 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<int> parent(N + 1, -1), depth(N + 1, 0); |
| queue<int> 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); |
| } |
| } |
|
|
| |
| vector<vector<int>> children(N + 1); |
| for (int v = 1; v <= N; v++) if (v != root) { |
| if (parent[v] <= 0) { |
| |
| 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]); |
|
|
| |
| vector<vector<int>> 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; |
| 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<int>& height_out) -> bool { |
| height_out.assign(N + 1, 0); |
|
|
| vector<int> 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<int> 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; |
| 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<int> h; |
| if (!compute_heights(K, h)) return false; |
|
|
| |
| 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<int> height; |
| bool ok = compute_heights(K, height); |
| if (!ok) { |
| K = 240; |
| compute_heights(K, height); |
| } |
|
|
| |
| for (int u = 1; u <= N; u++) sort(children[u].begin(), children[u].end()); |
| for (int u = 1; u <= N; u++) { |
| |
| sort(patches[u].begin(), patches[u].end()); |
| } |
|
|
| vector<vector<int>> C(K, vector<int>(K, root)); |
|
|
| struct Rect { int top, left, bottom, right; }; |
|
|
| function<void(int, Rect)> 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; |
|
|
| |
| 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; |
| } |
| }; |
|
|
| layout(root, Rect{0, 0, K - 1, K - 1}); |
|
|
| auto validate = [&]() -> bool { |
| vector<int> 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()) { |
| |
| K = 240; |
| compute_heights(K, height); |
| C.assign(K, vector<int>(K, root)); |
| layout(root, Rect{0, 0, K - 1, K - 1}); |
| |
| } |
|
|
| 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<int> 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; |
| } |