#include <cstdio>
#include <cassert>
#include <vector>
#include <algorithm>
using namespace std;
class Point {
public:
int x, y;
Point(const int _x = 0, const int _y = 0):
x(_x),
y(_y) {}
bool operator==(const Point &other) const {
return (x == other.x && y == other.y);
}
};
inline int Det(const Point &p1, const Point &p2, const Point &p3) {
return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p1.x * p3.y - p2.x * p1.y - p3.x * p2.y;
}
class Segment {
public:
Point e1, e2;
Segment(const Point _e1, const Point _e2):
e1(_e1),
e2(_e2) {
if (e1.y > e2.y)
swap(e1, e2);
}
static bool OpenIntersection(const Segment &s1, const Segment &s2) {
if (s1.e1 == s1.e2 || s2.e1 == s2.e2)
return false;
if (Det(s1.e1, s1.e2, s2.e1) == 0 && Det(s1.e1, s1.e2, s2.e2) == 0) {
if (OpenIntervalIntersection(s1.e1.x, s1.e2.x, s2.e1.x, s2.e2.x))
return true;
if (OpenIntervalIntersection(s1.e1.y, s1.e2.y, s2.e1.y, s2.e2.y))
return true;
return false;
}
return (1LL * Det(s1.e1, s1.e2, s2.e1) * Det(s1.e1, s1.e2, s2.e2) < 0 && 1LL * Det(s2.e1, s2.e2, s1.e1) * Det(s2.e1, s2.e2, s1.e2) < 0);
}
private:
static bool OpenIntervalIntersection(int x1, int x2, int y1, int y2) {
if (x1 > x2)
swap(x1, x2);
if (y1 > y2)
swap(y1, y2);
if (x1 > y1) {
swap(x1, y1);
swap(x2, y2);
}
return y1 < x2;
}
};
class Polygon {
public:
vector<Segment> edges;
Polygon():
edges(vector<Segment>()) {}
Polygon(const vector<Point> &points) {
for (int i = 0; i < int(points.size()); ++i)
edges.push_back(Segment(points[i], points[(i + 1) % int(points.size())]));
}
bool IsInside(const Point &p) const {
int intersect = 0;
for (const auto &segment: edges)
if (segment.e1.y < p.y && p.y <= segment.e2.y && Det(segment.e1, segment.e2, p) < 0)
++intersect;
return intersect % 2 == 1;
}
};
vector<Point> Points;
Polygon P;
int N;
vector< pair<int, int> > Triangulation;
inline bool CheckSegment(const Segment &edge) {
for (const auto &e: P.edges)
if (Segment::OpenIntersection(e, edge))
return false;
for (const auto &e: Triangulation)
if (Segment::OpenIntersection(Segment(Points[e.first], Points[e.second]), edge))
return false;
return P.IsInside(Point((edge.e1.x + edge.e2.x) / 2, (edge.e1.y + edge.e2.y) / 2));
}
void Solve() {
Triangulation = vector< pair<int, int> >();
for (int i = 0; i < N; ++i)
for (int j = (i + 2) % N; (j + 1) % N != i; ++j)
if (CheckSegment(Segment(Points[i], Points[j])))
Triangulation.push_back(make_pair(i, j));
sort(Triangulation.begin(), Triangulation.end());
}
void Read() {
assert(scanf("%d", &N) == 1);
Points = vector<Point>(N);
for (int i = 0; i < N; ++i) {
assert(scanf("%d %d", &Points[i].x, &Points[i].y) == 2);
Points[i].x *= 2;
Points[i].y *= 2;
}
P = Polygon(Points);
}
void Print() {
for (const auto &segment: Triangulation)
printf("%d %d\n", segment.first, segment.second);
}
int main() {
assert(freopen("triangulare.in", "r", stdin));
assert(freopen("triangulare.out", "w", stdout));
int testCount;
assert(scanf("%d", &testCount) == 1);
for (; testCount > 0; --testCount) {
Read();
Solve();
Print();
}
return 0;
}