#include #include using namespace std; using namespace atcoder; #define REP(i,a,n) for(int i=(a); i<(int)(n); i++) #define rep(i,n) REP(i,0,n) #define FOR(it,c) for(__typeof((c).begin()) it=(c).begin(); it!=(c).end(); ++it) #define ALLOF(c) (c).begin(), (c).end() typedef long long ll; typedef unsigned long long ull; //using mint = modint1000000007; //using mint = modint998244353; class Timer { std::chrono::system_clock::time_point start_time; std::chrono::system_clock::time_point getNow() { return std::chrono::system_clock::now(); } public: void start() { start_time = getNow(); } float getSec() { float count = std::chrono::duration_cast(getNow() - start_time).count(); return count / 1e6; } }; uint32_t xor128() { static uint32_t x = 123456789, y = 362436069, z = 521288629, w = 88675123; uint32_t t; t = (x ^ (x << 11)); x = y; y = z; z = w; return w = (w ^ (w >> 19)) ^ (t ^ (t >> 8)); } struct P { int t,i; double y, x; P():t(0),i(0),y(0),x(0){} P(int t, int i, double y, double x):t(t),i(i),y(y),x(x){} }; double distance(const P& a, const P& b) { static constexpr double alpha = 5.0; if(a.t == 1 && b.t == 1){ return alpha*alpha*((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } else if(a.t == 1 || b.t == 1){ return alpha * ((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y)); } else{ return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y); } } vector kmeans(const vector

& p, int M){ vector

r; rep(i,M) r.emplace_back(p[i]); vector ret(p.size()); //rep(i,ret.size()) ret[i] = i%M; rep(i,ret.size()) ret[i] = xor128()%M; rep(t,1000000){ bool change = false; vector

g(M); rep(i,p.size()){ g[ret[i]].y += p[i].y; g[ret[i]].x += p[i].x; g[ret[i]].i++; } rep(i,M){ if(g[i].i == 0){ int r = xor128()%p.size(); g[i].y = p[r].y; g[i].x = p[r].x; }else{ g[i].y /= g[i].i; g[i].x /= g[i].i; } } rep(i,p.size()){ double mind = 1e9; int minj = 0; rep(j,M){ double d = distance(p[i],g[j]); if(mind > d){ mind = d; minj = j; } } if(ret[i] != minj){ change = true; ret[i] = minj; } } if(!change) break; } return ret; } vector small_tsp(const vector

& v){ int N = v.size(); double tour_distance = 0; vector tour(N); for (int i = 0; i < N; i++) { tour[i] = i; tour_distance += distance(v[tour[i]], v[tour[(i + 1) % N]]); } double best_distance = tour_distance; vector best_tour = tour; do { tour_distance = 0; for (int i = 0; i < N; i++) { tour_distance += distance(v[tour[i]], v[tour[(i + 1) % N]]); } if (best_distance > tour_distance) { best_distance = tour_distance; best_tour = tour; } } while (next_permutation(tour.begin(), tour.end())); while(best_tour[0] != 0) rotate(best_tour.begin(), best_tour.begin()+1,best_tour.end()); return best_tour; } struct ST { int i; double ox, oy; ll x, y; }; bool operator<(const ST& a, const ST& b){ int sa = -1; if(a.x>=0 && a.y>=0) sa = 1; else if(a.x<=0 && a.y>=0) sa = 2; else if(a.x<=0 && a.y<=0) sa = 3; else if(a.x>=0 && a.y<=0) sa = 4; int sb = -1; if(b.x>=0 && b.y>=0) sb = 1; else if(b.x<=0 && b.y>=0) sb = 2; else if(b.x<=0 && b.y<=0) sb = 3; else if(b.x>=0 && b.y<=0) sb = 4; if(sa != sb) return sa < sb; return a.x * b.y - b.x * a.y > 0; } int N, M; vector

planets; ll calc_score(const vector

& ss, const vector>& ans){ double ret = 0; rep(i,ans.size()-1){ P p1, p2; if(ans[i].first == 1) p1 = planets[ans[i].second-1]; if(ans[i].first == 2) p1 = ss[ans[i].second-1]; if(ans[i+1].first == 1) p2 = planets[ans[i+1].second-1]; if(ans[i+1].first == 2) p2 = ss[ans[i+1].second-1]; ret += distance(p1, p2); } return (ll)(1e9 / (1000.0 + sqrt(ret))); } Timer timer; static constexpr double TIME_LIMIT = 0.95; int main(){ timer.start(); cin >> N >> M; rep(i,N){ ll y, x; cin >> y >> x; planets.emplace_back(1,i+1,y,x); } vector> best_ans; vector

best_ss; ll best_score = 0; while(true){ double sec = timer.getSec(); if(sec > TIME_LIMIT) break; vector cluster = kmeans(planets,M); if(sec > TIME_LIMIT) break; vector

ss(M); vector ss_num(M,0); rep(i,planets.size()){ ss[cluster[i]].y += planets[i].y; ss[cluster[i]].x += planets[i].x; ss_num[cluster[i]]++; } rep(i,M){ ss[i].t = 2; ss[i].i = i+1; if(ss_num[i] == 0) continue; ss[i].y /= ss_num[i]; ss[i].x /= ss_num[i]; } if(cluster[0] != 0){ int c = cluster[0]; rep(i,cluster.size()){ if(cluster[i] == c) cluster[i] = 0; else if(cluster[i] == 0) cluster[i] = c; } swap(ss[0], ss[c]); swap(ss_num[0], ss_num[c]); ss[0].i = 1; ss[c].i = c+1; } vector

groups[10]; rep(i,planets.size()){ if(planets[i].i == 1) continue; groups[cluster[i]].push_back(planets[i]); } if(sec > TIME_LIMIT) break; vector ss_tsp = small_tsp(ss); if(sec > TIME_LIMIT) break; vector> ans; ans.emplace_back(1,1); rep(i,ss_tsp.size()){ if(ss_num[ss_tsp[i]] == 0) continue; ans.emplace_back(2,ss[ss_tsp[i]].i); vector sts; rep(j,groups[ss_tsp[i]].size()){ sts.push_back((ST){groups[ss_tsp[i]][j].i,groups[ss_tsp[i]][j].x,groups[ss_tsp[i]][j].y,(ll)(groups[ss_tsp[i]][j].x-ss[ss_tsp[i]].x),(ll)(groups[ss_tsp[i]][j].y-ss[ss_tsp[i]].y)}); } sort(ALLOF(sts)); ans.emplace_back(1,sts[0].i); rep(j,sts.size()-1){ double d1 = distance((P){1,0,sts[j].oy,sts[j].ox},(P){1,0,sts[j+1].oy,sts[j+1].ox}); double d2 = distance((P){1,0,sts[j].oy,sts[j].ox},(P){2,0,ss[ss_tsp[i]].y,ss[ss_tsp[i]].x}) + distance((P){2,0,ss[ss_tsp[i]].y,ss[ss_tsp[i]].x},(P){1,0,sts[j+1].oy,sts[j+1].ox}); if(d1 < d2){ ans.emplace_back(1,sts[j+1].i); }else{ ans.emplace_back(2,ss[ss_tsp[i]].i); ans.emplace_back(1,sts[j+1].i); } } ans.emplace_back(2,ss[ss_tsp[i]].i); } ans.emplace_back(2,ss[ss_tsp[0]].i); ans.emplace_back(1,1); if(sec > TIME_LIMIT) break; ll score = calc_score(ss,ans); //cerr << score << endl; if(best_score < score){ best_score = score; best_ans = ans; best_ss = ss; } } cerr << best_score << endl; rep(i,M){ cout << (int)(best_ss[i].y) << " " << (int)(best_ss[i].x) << endl; } cout << best_ans.size() << endl; rep(i,best_ans.size()){ cout << best_ans[i].first << " " << best_ans[i].second << endl; } return 0; }