| #include <iostream> |
| #include <vector> |
| #include <cmath> |
| #include <cstdlib> |
| #include <ctime> |
| #include <algorithm> |
| #include <numeric> |
|
|
| using namespace std; |
|
|
| |
| inline double rand_double() { |
| return (double)rand() / (RAND_MAX + 1.0); |
| } |
|
|
| |
| inline int rand_int(int n) { |
| return rand() % n; |
| } |
|
|
| |
| std::vector<std::vector<int>> create_map(int N, int M, std::vector<int> A, std::vector<int> B) { |
| |
| |
| int min_K_area = ceil(sqrt(N)); |
| |
| |
| |
| |
| |
| int min_K_edges = 0; |
| if (M > 0) { |
| |
| min_K_edges = ceil(sqrt(M / 2.0)); |
| } |
| |
| int K = max(min_K_area, min_K_edges); |
| if (K < 1) K = 1; |
| |
| |
| |
| static bool adj[45][45]; |
| for(int i=0; i<=N; ++i) |
| for(int j=0; j<=N; ++j) adj[i][j] = false; |
| |
| for(int i=0; i<M; ++i) { |
| adj[A[i]][B[i]] = true; |
| adj[B[i]][A[i]] = true; |
| } |
| |
| |
| clock_t start_time = clock(); |
| |
| while (true) { |
| int num_cells = K * K; |
| |
| |
| vector<vector<int>> grid(K, vector<int>(K)); |
| |
| |
| vector<int> init_colors; |
| init_colors.reserve(num_cells); |
| for(int i=1; i<=N; ++i) init_colors.push_back(i); |
| while(init_colors.size() < num_cells) init_colors.push_back(rand_int(N)+1); |
| random_shuffle(init_colors.begin(), init_colors.end()); |
| |
| for(int i=0; i<num_cells; ++i) { |
| grid[i/K][i%K] = init_colors[i]; |
| } |
| |
| |
| |
| static int edge_counts[45][45]; |
| for(int i=0; i<=N; ++i) |
| for(int j=0; j<=N; ++j) edge_counts[i][j] = 0; |
| |
| int invalid_adj = 0; |
| int color_counts[45] = {0}; |
| |
| |
| auto update_stats_full = [&]() { |
| invalid_adj = 0; |
| for(int i=1; i<=N; ++i) { |
| for(int j=1; j<=N; ++j) edge_counts[i][j] = 0; |
| color_counts[i] = 0; |
| } |
| |
| for(int r=0; r<K; ++r) { |
| for(int c=0; c<K; ++c) { |
| int u = grid[r][c]; |
| color_counts[u]++; |
| |
| if (c+1 < K) { |
| int v = grid[r][c+1]; |
| if (u != v) { |
| int mn = min(u, v), mx = max(u, v); |
| edge_counts[mn][mx]++; |
| if (!adj[mn][mx]) invalid_adj++; |
| } |
| } |
| |
| if (r+1 < K) { |
| int v = grid[r+1][c]; |
| if (u != v) { |
| int mn = min(u, v), mx = max(u, v); |
| edge_counts[mn][mx]++; |
| if (!adj[mn][mx]) invalid_adj++; |
| } |
| } |
| } |
| } |
| }; |
| |
| update_stats_full(); |
| |
| int missing_colors = 0; |
| for(int i=1; i<=N; ++i) if(color_counts[i] == 0) missing_colors++; |
| |
| int missing_edges = 0; |
| for(int i=0; i<M; ++i) { |
| if(edge_counts[A[i]][B[i]] == 0) missing_edges++; |
| } |
| |
| long long current_score = (long long)invalid_adj * 5000 + (long long)missing_colors * 5000 + (long long)missing_edges * 20; |
| |
| if (current_score == 0) return grid; |
| |
| |
| double T = 2.0; |
| double min_T = 0.001; |
| double cooling = 0.9999; |
| int max_iters = 100000; |
| if (K > 15) max_iters = 150000; |
| if (K > 30) max_iters = 50000; |
| |
| |
| double elapsed = (double)(clock() - start_time) / CLOCKS_PER_SEC; |
| if (elapsed > 1.0) max_iters = 20000; |
| if (elapsed > 1.8) { |
| |
| |
| } |
|
|
| for(int iter=0; iter<max_iters; ++iter) { |
| int r = rand_int(K); |
| int c = rand_int(K); |
| int old_c = grid[r][c]; |
| int new_c = rand_int(N) + 1; |
| |
| if (old_c == new_c) continue; |
| |
| |
| int d_inv = 0; |
| vector<pair<int, int>> decs, incs; |
| decs.reserve(4); incs.reserve(4); |
| |
| int nr, nc; |
| int dirs[4][2] = {{-1,0}, {1,0}, {0,-1}, {0,1}}; |
| |
| for(int k=0; k<4; ++k) { |
| nr = r + dirs[k][0]; |
| nc = c + dirs[k][1]; |
| if (nr >= 0 && nr < K && nc >= 0 && nc < K) { |
| int neighbor = grid[nr][nc]; |
| if (neighbor != old_c) { |
| int mn = min(old_c, neighbor); |
| int mx = max(old_c, neighbor); |
| if (!adj[mn][mx]) d_inv--; |
| decs.push_back({mn, mx}); |
| } |
| if (neighbor != new_c) { |
| int mn = min(new_c, neighbor); |
| int mx = max(new_c, neighbor); |
| if (!adj[mn][mx]) d_inv++; |
| incs.push_back({mn, mx}); |
| } |
| } |
| } |
| |
| int d_col = 0; |
| if (color_counts[old_c] == 1) d_col++; |
| if (color_counts[new_c] == 0) d_col--; |
| |
| int d_miss_edge = 0; |
| for(auto &p : decs) { |
| if (edge_counts[p.first][p.second] == 1 && adj[p.first][p.second]) d_miss_edge++; |
| edge_counts[p.first][p.second]--; |
| } |
| for(auto &p : incs) { |
| if (edge_counts[p.first][p.second] == 0 && adj[p.first][p.second]) d_miss_edge--; |
| edge_counts[p.first][p.second]++; |
| } |
| |
| long long new_score = (long long)(invalid_adj + d_inv) * 5000 + |
| (long long)(missing_colors + d_col) * 5000 + |
| (long long)(missing_edges + d_miss_edge) * 20; |
| |
| bool accept = false; |
| if (new_score <= current_score) accept = true; |
| else { |
| if (rand_double() < exp(-(new_score - current_score) / T)) accept = true; |
| } |
| |
| if (accept) { |
| grid[r][c] = new_c; |
| invalid_adj += d_inv; |
| missing_colors += d_col; |
| missing_edges += d_miss_edge; |
| color_counts[old_c]--; |
| color_counts[new_c]++; |
| current_score = new_score; |
| if (current_score == 0) return grid; |
| } else { |
| |
| for(auto &p : incs) edge_counts[p.first][p.second]--; |
| for(auto &p : decs) edge_counts[p.first][p.second]++; |
| } |
| |
| T *= cooling; |
| if (T < min_T) T = min_T; |
| } |
| |
| K++; |
| if (K > 240) K = 240; |
| } |
| } |
|
|
| int main() { |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
| srand(42); |
| int T; |
| if (cin >> T) { |
| 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>> result = create_map(N, M, A, B); |
| int P = result.size(); |
| cout << P << "\n"; |
| for(int i=0; i<P; ++i) { |
| cout << result[i].size() << (i == P-1 ? "" : " "); |
| } |
| cout << "\n"; |
| for(int i=0; i<P; ++i) { |
| for(int j=0; j<(int)result[i].size(); ++j) { |
| cout << result[i][j] << (j == result[i].size()-1 ? "" : " "); |
| } |
| cout << "\n"; |
| } |
| } |
| } |
| return 0; |
| } |