#include <bits/stdc++.h>
using namespace std;
bool canConstructTree(int n, int d, int l) {
// Base cases
if (l > n) return false; // Can't have more leaves than nodes
if (n == 2) return (d == 1 && l == 2); // Special case for 2 nodes
// For d = 1, only star graph is possible
if (d == 1) return (n - 1 == l);
// For d = 2, we need a central node with leaves
if (d == 2) return (l <= n - 1 && l >= 2);
// For d >= 3:
// Maximum possible leaves = n - (d-1) + 1
// (path of length d needs d nodes, remaining can be leaves)
int maxLeaves = n - (d - 1);
// Minimum possible leaves = 2
// (at the ends of diameter path)
return (l >= 2 && l <= maxLeaves);
}
void constructTree(int n, int d, int l) {
if (!canConstructTree(n, d, l)) {
cout << -1 << "\n";
return;
}
if (d == 1) {
// Star graph
for (int i = 2; i <= n; i++) {
cout << "1 " << i << "\n";
}
return;
}
if (d == 2) {
// Center node with leaves
int center = 1;
int nonLeaves = n - l;
// Connect center to non-leaf nodes (if any besides center)
for (int i = 2; i <= nonLeaves; i++) {
cout << center << " " << i << "\n";
}
// Connect remaining nodes as leaves
for (int i = nonLeaves + 1; i <= n; i++) {
cout << center << " " << i << "\n";
}
return;
}
// For d >= 3:
// First create the diameter path
for (int i = 1; i < d; i++) {
cout << i << " " << i + 1 << "\n";
}
// Remaining nodes will be attached appropriately to maintain diameter d
int nextNode = d + 1;
int midPoint = (d + 1) / 2;
// Need to have exactly l leaves
int currentLeaves = 2; // ends of diameter path
// Attach remaining nodes to middle of path until we get required leaves
while (nextNode <= n) {
if (currentLeaves < l) {
// Add as leaf
cout << midPoint << " " << nextNode << "\n";
currentLeaves++;
} else {
// Add as non-leaf to maintain diameter
cout << midPoint << " " << nextNode << "\n";
}
nextNode++;
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
int n, d, l;
cin >> n >> d >> l;
constructTree(n, d, l);
}
return 0;
}