using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
class Yukico5007
{
static void Main(string[] args)
{
var sw = Stopwatch.StartNew();
var nums = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
var N = nums[0];
var M = nums[1];
var planets = new List<(int y, int x)>();
for (int i = 0; i < N; i++)
{
nums = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
planets.Add((nums[0], nums[1]));
}
var directCosts = new double[(N + 1) * (N + 1)];
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (i == j) continue;
var cost = Math.Sqrt(Math.Abs(planets[i].y - planets[j].y) * Math.Abs(planets[i].y - planets[j].y) +
Math.Abs(planets[i].x - planets[j].x) * Math.Abs(planets[i].x - planets[j].x));
directCosts[i * (N + 1) + j] = cost;
}
}
for (int i = 0; i < N; i++)
{
directCosts[(N + 1) * N + i] = directCosts[0 * (N + 1) + i];
directCosts[(N + 1) * i + N] = directCosts[i * (N + 1) + 0];
}
var inputs = new Inputs(sw, directCosts, null);
var solver = new Solver();
var command = solver.GetCommand(inputs);
command.Print();
}
}
class Inputs
{
/// 他の惑星を経由せずに直接飛ぶコスト(αは考慮しない)
public double[] DirectCosts;
/// 他の惑星を経由して飛ぶ最小コスト(αは考慮しない)
public double[] RouteCosts;
public Stopwatch Sw;
public const int N = 100;
public const int NP1 = 101;
public const int M = 8;
public const int A = 5;
public Inputs(Stopwatch sw, double[] directCosts, double[] routeCosts)
{
Sw = sw;
DirectCosts = directCosts;
RouteCosts = routeCosts;
}
}
class Outputs
{
public List<(int y, int x)> Stations = new();
public List<(int t, int r)> Route = new();
public void Print()
{
foreach (var pos in Stations)
{
Console.WriteLine($"{pos.y} {pos.x}");
}
Console.WriteLine(Route.Count);
foreach (var via in Route)
{
Console.WriteLine($"{via.t} {via.r}");
}
}
}
class Solver
{
public Outputs GetCommand(Inputs inputs)
{
var defaultRoute = Enumerable.Range(0, Inputs.N).Append(0).ToArray();
var twoOpt = new TwoOpt(Inputs.NP1, inputs.DirectCosts, defaultRoute, new Random(1728), inputs.Sw);
twoOpt.Exec();
var res = new Outputs();
for (int i = 0; i < Inputs.M; i++)
{
res.Stations.Add((0, 0));
}
foreach (var i in twoOpt.IdxByOrders)
{
res.Route.Add((1, i + 1));
}
return res;
}
}
public class TwoOpt
{
public readonly int NodeCount;
public readonly int NodeCount2;
public readonly double[] Costs;
/// idx番目に経由する点がvalue番目の要素
public readonly int[] IdxByOrders;
Random _random;
System.Diagnostics.Stopwatch _sw;
public TwoOpt(int n, double[] costs, int[] defaultOrder, Random random, System.Diagnostics.Stopwatch sw)
{
NodeCount = n;
NodeCount2 = defaultOrder.Length;
Costs = costs;
IdxByOrders = new int[NodeCount2];
Array.Copy(defaultOrder, IdxByOrders, NodeCount2);
_random = random;
_sw = sw;
}
public void Exec()
{
var cnt = 0;
var costsSpan = new Span(Costs);
while (_sw.ElapsedMilliseconds < 950)
{
for (int i = 0; i < 100; i++)
{
// 先頭、末尾は交換しない
var from1order = _random.Next(NodeCount2 - 4);
var from2order = _random.Next(from1order + 3, NodeCount2);
var from1 = IdxByOrders[from1order];
var from2 = IdxByOrders[from2order];
var to1 = IdxByOrders[from1order + 1];
var to2 = IdxByOrders[from2order - 1];
// コスト計算
var oldRouteCost = costsSpan[from1 * NodeCount + to1] + costsSpan[from2 * NodeCount + to2];
var newRouteCost = costsSpan[from1 * NodeCount + to2] + costsSpan[from2 * NodeCount + to1];
// 改善されていれば更新
if (newRouteCost < oldRouteCost) Swap(from1order, from2order);
}
cnt++;
}
}
///
/// 2点の接続を交換する
///
/// 点1のOrder順
/// 点2のOrder順
public void Swap(int from1order, int from2order)
{
Array.Reverse(IdxByOrders, from1order + 1, from2order - from1order - 1);
}
}