package main
import (
"bufio"
"io"
"os"
"sort"
"strconv"
"strings"
)
type FastScanner struct {
data []byte
pos int
n int
}
func NewFastScanner() *FastScanner {
data, _ := io.ReadAll(os.Stdin)
return &FastScanner{data: data, n: len(data)}
}
func (fs *FastScanner) NextInt() int {
for fs.pos < fs.n {
c := fs.data[fs.pos]
if c == '-' || (c >= '0' && c <= '9') {
break
}
fs.pos++
}
sign := 1
if fs.data[fs.pos] == '-' {
sign = -1
fs.pos++
}
val := 0
for fs.pos < fs.n {
c := fs.data[fs.pos]
if c < '0' || c > '9' {
break
}
val = val*10 + int(c-'0')
fs.pos++
}
return sign * val
}
type Point struct {
x, y int
idx int
}
func main() {
fs := NewFastScanner()
t := fs.NextInt()
var sb strings.Builder
for ; t > 0; t-- {
n := fs.NextInt()
pts := make([]Point, n)
for i := 0; i < n; i++ {
pts[i] = Point{x: fs.NextInt(), y: fs.NextInt(), idx: i + 1}
}
xLow := make([]bool, n+1)
yLow := make([]bool, n+1)
ord := make([]Point, n)
copy(ord, pts)
sort.Slice(ord, func(i, j int) bool {
if ord[i].x != ord[j].x {
return ord[i].x < ord[j].x
}
if ord[i].y != ord[j].y {
return ord[i].y < ord[j].y
}
return ord[i].idx < ord[j].idx
})
for i := 0; i < n/2; i++ {
xLow[ord[i].idx] = true
}
copy(ord, pts)
sort.Slice(ord, func(i, j int) bool {
if ord[i].y != ord[j].y {
return ord[i].y < ord[j].y
}
if ord[i].x != ord[j].x {
return ord[i].x < ord[j].x
}
return ord[i].idx < ord[j].idx
})
for i := 0; i < n/2; i++ {
yLow[ord[i].idx] = true
}
a := make([]int, 0)
b := make([]int, 0)
c := make([]int, 0)
d := make([]int, 0)
for _, p := range pts {
xl := xLow[p.idx]
yl := yLow[p.idx]
if xl {
if yl {
a = append(a, p.idx)
} else {
b = append(b, p.idx)
}
} else {
if yl {
c = append(c, p.idx)
} else {
d = append(d, p.idx)
}
}
}
for i := 0; i < len(a); i++ {
sb.WriteString(strconv.Itoa(a[i]))
sb.WriteByte(' ')
sb.WriteString(strconv.Itoa(d[i]))
sb.WriteByte('\n')
}
for i := 0; i < len(b); i++ {
sb.WriteString(strconv.Itoa(b[i]))
sb.WriteByte(' ')
sb.WriteString(strconv.Itoa(c[i]))
sb.WriteByte('\n')
}
}
w := bufio.NewWriterSize(os.Stdout, 1<<20)
w.WriteString(sb.String())
w.Flush()
}