description: Lord Omkar would like to have a tree with n nodes (3 ≤ n ≤ 10^5) and has asked his disciples to construct the tree. However, Lord Omkar has created m (1 ≤ m < n) restrictions to ensure that the tree will be as heavenly as possible. 
  
  A tree with n nodes is an connected undirected graph with n nodes and n-1 edges. Note that for any two nodes, there is exactly one simple path between them, where a simple path is a path between two nodes that does not contain any node more than once.
  
  Here is an example of a tree: 
  
  <image>
  
  A restriction consists of 3 pairwise distinct integers, a, b, and c (1 ≤ a,b,c ≤ n). It signifies that node b cannot lie on the simple path between node a and node c. 
  
  Can you help Lord Omkar and become his most trusted disciple? You will need to find heavenly trees for multiple sets of restrictions. It can be shown that a heavenly tree will always exist for any set of restrictions under the given constraints.
  
  Input
  
  Each test contains multiple test cases. The first line contains the number of test cases t (1 ≤ t ≤ 10^4). Description of the test cases follows.
  
  The first line of each test case contains two integers, n and m (3 ≤ n ≤ 10^5, 1 ≤ m < n), representing the size of the tree and the number of restrictions.
  
  The i-th of the next m lines contains three integers a_i, b_i, c_i (1 ≤ a_i, b_i, c_i ≤ n, a, b, c are distinct), signifying that node b_i cannot lie on the simple path between nodes a_i and c_i. 
  
  It is guaranteed that the sum of n across all test cases will not exceed 10^5.
  
  Output
  
  For each test case, output n-1 lines representing the n-1 edges in the tree. On each line, output two integers u and v (1 ≤ u, v ≤ n, u ≠ v) signifying that there is an edge between nodes u and v. Given edges have to form a tree that satisfies Omkar's restrictions.
  
  Example
  
  Input
  
  
  2
  7 4
  1 2 3
  3 4 5
  5 6 7
  6 5 4
  5 3
  1 2 3
  2 3 4
  3 4 5
  
  
  Output
  
  
  1 2
  1 3
  3 5
  3 4
  2 7
  7 6
  5 1
  1 3
  3 2
  2 4
  
  Note
  
  The output of the first sample case corresponds to the following tree: 
  
  <image> For the first restriction, the simple path between 1 and 3 is 1, 3, which doesn't contain 2. The simple path between 3 and 5 is 3, 5, which doesn't contain 4. The simple path between 5 and 7 is 5, 3, 1, 2, 7, which doesn't contain 6. The simple path between 6 and 4 is 6, 7, 2, 1, 3, 4, which doesn't contain 5. Thus, this tree meets all of the restrictions.
  
  The output of the second sample case corresponds to the following tree: 
  
  <image>
solution: import java.io.OutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.PrintWriter;
  import java.io.OutputStream;
  import java.io.IOException;
  import java.io.InputStreamReader;
  import java.io.FileNotFoundException;
  import java.util.StringTokenizer;
  import java.io.Writer;
  import java.io.BufferedReader;
  import java.io.InputStream;
  
  /**
   * Built using CHelper plug-in
   * Actual solution is at the top
   *
   * @author Asgar Javadov
   */
  public class Main {
      public static void main(String[] args) {
          InputStream inputStream = System.in;
          OutputStream outputStream = System.out;
          InputReader in = new InputReader(inputStream);
          OutputWriter out = new OutputWriter(outputStream);
          BOmkarAndHeavenlyTree solver = new BOmkarAndHeavenlyTree();
          int testCount = Integer.parseInt(in.next());
          for (int i = 1; i <= testCount; i++)
              solver.solve(i, in, out);
          out.close();
      }
  
      static class BOmkarAndHeavenlyTree {
          public void solve(int testNumber, InputReader in, OutputWriter out) {
              int n = in.nextInt();
              int m = in.nextInt();
              var a = new int[m];
              var b = new int[m];
              var c = new int[m];
  
              var seen = new boolean[n + 1];
              for (int i = 0; i < m; i++) {
                  a[i] = in.nextInt();
                  b[i] = in.nextInt();
                  seen[b[i]] = true;
                  c[i] = in.nextInt();
              }
  
              int root = 1;
              for (; root <= n && seen[root]; root++) ;
  
              for (int i = 1; i <= n; i++) {
                  if (i == root) continue;
                  out.print(root);
                  out.space();
                  out.println(i);
              }
          }
  
      }
  
      static class InputReader extends BufferedReader {
          StringTokenizer tokenizer;
  
          public InputReader(InputStream inputStream) {
              super(new InputStreamReader(inputStream), 32768);
          }
  
          public InputReader(String filename) {
              super(new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(filename)));
          }
  
          public String next() {
              while (tokenizer == null || !tokenizer.hasMoreTokens()) {
                  try {
                      String line = readLine();
                      if (line == null) continue;
                      tokenizer = new StringTokenizer(line);
                  } catch (IOException e) {
                      throw new RuntimeException();
                  }
              }
              return tokenizer.nextToken();
          }
  
          public Integer nextInt() {
              return Integer.valueOf(next());
          }
  
      }
  
      static class OutputWriter extends PrintWriter {
          public OutputWriter(OutputStream outputStream) {
              super(outputStream);
          }
  
          public OutputWriter(Writer writer) {
              super(writer);
          }
  
          public OutputWriter(String filename) throws FileNotFoundException {
              super(filename);
          }
  
          public void space() {
              print(' ');
          }
  
          public void close() {
              super.close();
          }
  
      }
  }
  
  