#include <bits/stdc++.h>
using namespace std;
struct P{int x,y;};
double dist(const P &a,const P &b){double dx=a.x-b.x,dy=a.y-b.y;return sqrt(dx*dx+dy*dy);}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N,K;
if(!(cin>>N>>K)) return 0;
vector<P> pts(N);
for(int i=0;i<N;i++) cin>>pts[i].x>>pts[i].y;
const int GW=10, GH=14;
int cells = GW*GH;
vector<vector<int>> cluster(max(K,cells));
int MAXC=814000;
for(int i=0;i<N;i++){
int gx = (long long)pts[i].x * GW / (MAXC+1);
int gy = (long long)pts[i].y * GH / (MAXC+1);
if(gx<0) gx=0; if(gx>=GW) gx=GW-1;
if(gy<0) gy=0; if(gy>=GH) gy=GH-1;
int id = gy*GW + gx;
cluster[id].push_back(i);
}
if((int)cluster.size() < K) cluster.resize(K);
vector<int> emptyCells;
for(int i=0;i<cells;i++) if(cluster[i].empty()) emptyCells.push_back(i);
auto largest_idx = [&](void)->int{
int idx=-1, mx=-1;
for(int i=0;i<cells;i++){ if((int)cluster[i].size()>mx){mx=cluster[i].size(); idx=i;} }
return idx;
};
while(!emptyCells.empty()){
int to = emptyCells.back(); emptyCells.pop_back();
int from = largest_idx();
if(from==to) break;
if(cluster[from].size()<=1){
int found=-1;
for(int i=0;i<cells;i++) if((int)cluster[i].size()>1){ found=i; break;}
if(found==-1) break;
from=found;
}
int mv = cluster[from].back(); cluster[from].pop_back();
cluster[to].push_back(mv);
}
vector<vector<int>> tours(cells);
auto build_nn = [&](const vector<int>&pts_idx)->vector<int>{
int m = pts_idx.size();
if(m==0) return {};
vector<int> tour; tour.reserve(m);
vector<char> used(m,0);
int cur = 0;
tour.push_back(pts_idx[cur]);
used[cur]=1;
for(int t=1;t<m;t++){
int best=-1; double bd=1e300;
for(int j=0;j<m;j++) if(!used[j]){
double d = dist(pts[ tour.back() ], pts[ pts_idx[j] ]);
if(d<bd){ bd=d; best=j; }
}
used[best]=1;
tour.push_back(pts_idx[best]);
}
return tour;
};
auto tour_len = [&](const vector<int>&t)->double{
int m=t.size(); if(m==0) return 0.0;
double s=0;
for(int i=0;i<m;i++){
const P &a=pts[t[i]], &b=pts[t[(i+1)%m]];
s += dist(a,b);
}
return s;
};
auto run_2opt = [&](vector<int>&t, int iter_limit){
int n = t.size();
if(n<=2) return;
bool improved=true;
int iter=0;
while(improved && iter<iter_limit){
improved=false;
for(int i=0;i<n-1;i++){
for(int j=i+2;j<n + (i>0?0:-1);j++){
int a=i, b=(i+1)%n, c=j%n, d=(j+1)%n;
double before = dist(pts[t[a]],pts[t[b]]) + dist(pts[t[c]],pts[t[d]]);
double after = dist(pts[t[a]],pts[t[c]]) + dist(pts[t[b]],pts[t[d]]);
if(after + 1e-12 < before){
if(a < c){
reverse(t.begin()+b, t.begin()+c+1);
} else {
vector<int> nt;
for(int k=0;k<=a;k++) nt.push_back(t[k]);
for(int k=c;k>=b;k--) nt.push_back(t[k]);
for(int k=a+1;k<=c-1;k++) nt.push_back(t[k]);
t.swap(nt);
}
improved=true;
goto NEXT;
}
}
}
NEXT:
iter++;
}
};
for(int i=0;i<cells;i++){
tours[i] = build_nn(cluster[i]);
if(tours[i].size()>1) run_2opt(tours[i], 200);
}
vector<double> len(cells);
for(int i=0;i<cells;i++) len[i]=tour_len(tours[i]);
auto neighbors = [&](int id)->vector<int>{
int gx = id % GW;
int gy = id / GW;
vector<int> res;
for(int dx=-1;dx<=1;dx++) for(int dy=-1;dy<=1;dy++){
if(dx==0 && dy==0) continue;
int nx=gx+dx, ny=gy+dy;
if(nx>=0 && nx<GW && ny>=0 && ny<GH) ;
}
res.clear();
for(int dy=-1;dy<=1;dy++) for(int dx=-1;dx<=1;dx++){
if(dx==0 && dy==0) continue;
int nx = gx+dx, ny = gy+dy;
if(nx>=0 && nx< GW && ny>=0 && ny<GH) res.push_back(ny*GW+nx);
}
return res;
};
for(int iter=0; iter<200; iter++){
int worst = max_element(len.begin(), len.end()) - len.begin();
vector<int> nbs = neighbors(worst);
double bestgain = 1e-12;
int pick_from=-1, pick_to=-1, pick_pos=-1;
for(int nb : nbs){
if(nb<0 || nb>=cells) continue;
for(int idxPos=0; idxPos<(int)tours[worst].size(); idxPos++){
int city = tours[worst][idxPos];
int prev = tours[worst][ (idxPos-1 + tours[worst].size())%tours[worst].size() ];
int next = tours[worst][ (idxPos+1) % tours[worst].size() ];
double removeCost = dist(pts[prev], pts[city]) + dist(pts[city], pts[next]) - dist(pts[prev], pts[next]);
double bestInsert = 1e300;
int bestI = -1;
int m = tours[nb].size();
if(m==0){
bestInsert = 2*0.0;
bestI = 0;
} else {
for(int j=0;j<m;j++){
int a = tours[nb][j];
int b = tours[nb][ (j+1)%m ];
double ins = dist(pts[a], pts[city]) + dist(pts[city], pts[b]) - dist(pts[a], pts[b]);
if(ins < bestInsert){ bestInsert = ins; bestI = j+1; }
}
}
double newWorstLen = len[worst] - removeCost;
double newNbLen = len[nb] + bestInsert;
double newMax = newWorstLen;
if(newNbLen > newMax) newMax = newNbLen;
double oldMax = max(len[worst], len[nb]);
double gain = oldMax - newMax;
if(gain > bestgain){
bestgain = gain;
pick_from = idxPos;
pick_to = nb;
pick_pos = bestI;
}
}
}
if(pick_from==-1) break;
int city = tours[worst][pick_from];
tours[worst].erase(tours[worst].begin()+pick_from);
if(pick_pos > (int)tours[pick_to].size()) pick_pos = tours[pick_to].size();
tours[pick_to].insert(tours[pick_to].begin()+pick_pos, city);
len[worst]=tour_len(tours[worst]);
len[pick_to]=tour_len(tours[pick_to]);
if(tours[worst].size()>1) run_2opt(tours[worst], 60);
if(tours[pick_to].size()>1) run_2opt(tours[pick_to], 60);
len[worst]=tour_len(tours[worst]);
len[pick_to]=tour_len(tours[pick_to]);
}
for(int i=0;i<K;i++){
if(i < cells){
int m = tours[i].size();
cout<<m;
for(int j=0;j<m;j++) cout<<" "<<(tours[i][j]+1);
cout<<"\n";
} else {
cout<<"1 "<<1<<"\n";
}
}
return 0;
}