#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; #if defined(_MSC_VER) || defined(__APPLE_CC__) #define LOCAL #endif const int TIME_LIMIT = 6000 - 100; const int INF = 1000000000; typedef pair II; std::random_device seed_gen; std::mt19937_64 engine(seed_gen()); auto start_time = chrono::high_resolution_clock::now(); inline int get_elapsed_ms() { return int(chrono::duration_cast(chrono::high_resolution_clock::now() - start_time).count()); } struct Solver { int N; int M; vector y, x, g; void input() { cin >> N >> M; y.resize(N + M); x.resize(N + M); g.resize(N + M); for (int i = 0; i < N; ++i) { cin >> y[i] >> x[i]; } } void prepare() { } int64_t get_dist(int a, int b) { int dx = x[b] - x[a], dy = y[b] - y[a]; int64_t dist = dx * dx + dy * dy; if (a < N) dist *= 5; if (b < N) dist *= 5; return dist; } void output(const vector& ans) { for (int i = 0; i < M; ++i) { cout << y[i + N] << " " << x[i + N] << endl; } cout << ans.size() << endl; for (int x : ans) { if (x < N) { cout << "1 " << (x + 1) << endl; } else { cout << "2 " << (x - N + 1) << endl; } } } bool classify() { for (int i = 0; i < N; ++i) { g[i] = engine() % M; } bool done = false; while (!done) { done = true; vector xx(M), yy(M), cnt(M); for (int i = 0; i < N; ++i) { xx[g[i]] += x[i]; yy[g[i]] += y[i]; cnt[g[i]] += 1; } for (int i = 0; i < M; ++i) { if (cnt[i]) { xx[i] /= cnt[i]; yy[i] /= cnt[i]; x[N + i] = xx[i]; y[N + i] = yy[i]; } } for (int i = 0; i < N; ++i) { int md = INF, next_g = -1; for (int j = 0; j < M; ++j) { int dx = x[i] - xx[j], dy = y[i] - yy[j], d = dx * dx + dy * dy; if (d < md) { md = d; next_g = j; } } if (g[i] != next_g) { done = false; g[i] = next_g; } } } vector cnt(M); for (int i = 0; i < N; ++i) { cnt[g[i]] += 1; } for (int i = 0; i < M; ++i) { if (cnt[i] == 0) { return false; } } return true; } vector gen(int prev_point, int group, const vector& points) { vector r; if (points.size() > 60) { return r; } vector closest_points(points.size()); for (int i = 0; i < points.size(); ++i) { int64_t min_dist = 1LL << 60; int& closest = closest_points[i]; for (int j = 0; j < points.size(); ++j) { if (i == j) continue; int64_t dist = get_dist(points[i], points[j]); if (dist < min_dist) { min_dist = dist; closest = j; } } } int64_t min_cost = 1LL << 60; for (int i = 0; i < 15; ++i) { int64_t cost = 0, vis = 0, all = (1LL << points.size()) - 1; vector path; int p = prev_point, pi = -1; if (!points.empty() && points.front() == prev_point) { pi = 0; vis |= 1; } while (vis != all) { int next_index = -1, next = N + group; if (engine() % 2) { if (pi >= 0) { int next_candidate = closest_points[pi]; if ((vis & (1LL << next_candidate)) == 0) { next_index = next_candidate; next = points[next_index]; } } } while (p == next) { int next_candidate = engine() % points.size(); if ((vis & (1LL << next_candidate)) == 0) { next_index = next_candidate; next = points[next_index]; } } cost += get_dist(p, next); path.emplace_back(next); if (next_index >= 0) { vis |= (1LL << next_index); } pi = next_index; p = next; } cost += get_dist(path.empty() ? prev_point : path.back(), N + group); path.emplace_back(N + group); if (cost < min_cost) { min_cost = cost; r = path; } } return r; } vector gen(const vector &seq) { vector r; r.emplace_back(0); for (int gg = 0; gg < M; ++gg) { vector points; int target_group = seq[gg]; for (int i = 0; i < N; ++i) { if (g[i] == target_group) { points.emplace_back(i); } } for (auto x : gen(r.back(), target_group, points)) { r.emplace_back(x); } } for (auto x : gen(r.back(), seq[0], {})) { r.emplace_back(x); } r.emplace_back(0); return r; } int64_t evaluate(const vector& r) { int64_t s = 0; int prev = 0; for (int next : r) { s += get_dist(prev, next); prev = next; } return s; } void run() { int64_t min_score = 1LL << 60; vector ans; while (!classify()) { ; } vector seq(M+1); iota(seq.begin(), seq.end(), 0); seq[M] = g[0]; do { if (seq[0] == g[0]) { vector r = gen(seq); int64_t score = evaluate(r); if (score < min_score) { min_score = score; ans = r; } } } while (next_permutation(seq.begin(), seq.begin() + M)); output(ans); } }; int main(int argc, char* argv[]) { #if DEBUG freopen("in.txt", "r", stdin); #endif Solver solver; solver.input(); solver.prepare(); solver.run(); }