#include <bits/stdc++.h>
using namespace std;
bool canConstructTree(int n, int d, int l) {
// Basic validation
if (l < 2 || l > n - (d - 1)) return false; // Invalid number of leaves
if (d >= n) return false; // Diameter must be less than the number of nodes
// Special cases
if (n == 2) return (d == 1 && l == 2); // Only possible case for 2 nodes
// For diameter 1, tree must be a star with n-1 leaves
if (d == 1) return (l == n-1);
// For diameter 2, we need at least 2 leaves and at most n-1 leaves
if (d == 2) return (l >= 2 && l <= n-1);
// For general case with diameter d
// We need at least d+1 nodes for the main path
int nodesInPath = d + 1;
if (nodesInPath > n) return false;
// Maximum possible leaves is n - (d-1)
// Because we need at least d-1 internal nodes for the path
int maxPossibleLeaves = n - (d-1);
// Minimum leaves is 2 (at the ends of the diameter path)
return (l >= 2 && l <= maxPossibleLeaves);
}
void constructTree(int n, int d, int l) {
if (!canConstructTree(n, d, l)) {
cout << -1 << "\n";
return;
}
// Case 1: Diameter 1 (Star-shaped tree)
if (d == 1) {
for (int i = 2; i <= n; i++) {
cout << "1 " << i << "\n";
}
return;
}
// Case 2: Diameter 2 (Tree with one non-leaf node and center node)
if (d == 2) {
int center = 1;
int nonLeafNode = 2;
// Connect one non-leaf node to center
cout << center << " " << nonLeafNode << "\n";
// Distribute remaining nodes as leaves between center and non-leaf node
int remainingLeaves = l;
int currentNode = 3;
// Connect leaves to center
while (currentNode <= n && remainingLeaves > 1) {
cout << center << " " << currentNode << "\n";
currentNode++;
remainingLeaves--;
}
// Connect remaining leaves to non-leaf node
while (currentNode <= n) {
cout << nonLeafNode << " " << currentNode << "\n";
currentNode++;
}
return;
}
// Case 3: General case (d > 2)
// First create the diameter path
for (int i = 1; i <= d; i++) {
cout << i << " " << i + 1 << "\n";
}
int currentNode = d + 2;
int remainingLeaves = l - 2; // We already have 2 leaves at the ends
// Add remaining leaves, distributing them between endpoints
while (currentNode <= n && remainingLeaves > 0) {
if (remainingLeaves > 0) {
cout << "1 " << currentNode << "\n";
remainingLeaves--;
currentNode++;
}
if (remainingLeaves > 0 && currentNode <= n) {
cout << d + 1 << " " << currentNode << "\n";
remainingLeaves--;
currentNode++;
}
}
// If we have any remaining nodes, attach them to middle nodes
int middleNode = 2; // Start attaching to second node of path
while (currentNode <= n) {
cout << middleNode << " " << currentNode << "\n";
currentNode++;
middleNode = middleNode % d + 1; // Cycle through middle nodes
}
}
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;
}