#include #include #include #include #include #include #include using namespace std; // Helper to get random double in [0, 1) inline double rand_double() { return (double)rand() / (RAND_MAX + 1.0); } // Helper to get random int in [0, n-1] inline int rand_int(int n) { return rand() % n; } // Function to create the map std::vector> create_map(int N, int M, std::vector A, std::vector B) { // Determine bounds for K // We need K*K >= N to fit all colors int min_K_area = ceil(sqrt(N)); // We need enough adjacencies. // Total adjacencies in KxK grid is 2K(K-1). // We need to support M edges. // This is a loose lower bound, but K must be at least this. int min_K_edges = 0; if (M > 0) { // Solving 2K^2 - 2K >= M for K. Approximation 2K^2 approx M min_K_edges = ceil(sqrt(M / 2.0)); } int K = max(min_K_area, min_K_edges); if (K < 1) K = 1; // Adjacency matrix (1-based) // Using static array for speed given N <= 40 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> grid(K, vector(K)); // Ensure all colors present vector 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 15) max_iters = 150000; if (K > 30) max_iters = 50000; // Check time remaining double elapsed = (double)(clock() - start_time) / CLOCKS_PER_SEC; if (elapsed > 1.0) max_iters = 20000; if (elapsed > 1.8) { // If time is running out, just return what we have? // But we need a valid solution. We continue hoping to find one quickly or timeout. } for(int iter=0; iter> 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 { // Revert changes to edge_counts 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 A(M), B(M); for(int i=0; i> A[i] >> B[i]; } vector> result = create_map(N, M, A, B); int P = result.size(); cout << P << "\n"; for(int i=0; i