#include <bits/stdc++.h>
using namespace std;
vector<int> adj[200005];
vector<int> toposort;
bool color[200005];
bool visit[200005];
bool flag;
int mp[200005];
void topo(int index) {
  color[index] = true;
  for (int i = 0; i < adj[index].size(); i++) {
    int next = adj[index][i];
    if (color[next] == true) {
      flag = true;
      return;
    }
    if (!visit[next]) {
      visit[next] = true;
      topo(next);
    }
  }
  color[index] = false;
  toposort.push_back(index);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int t;
  cin >> t;
  while (t--) {
    int n, m;
    cin >> n >> m;
    memset(visit, 0, sizeof(visit));
    memset(color, 0, sizeof(color));
    memset(mp, 0, sizeof(mp));
    flag = false;
    vector<int> unx;
    vector<int> uny;
    vector<int> dix, diy;
    toposort.clear();
    for (int i = 0; i < m; i++) {
      int op, x, y;
      cin >> op >> x >> y;
      if (op == 1) {
        adj[x].push_back(y);
        dix.push_back(x);
        diy.push_back(y);
      } else {
        unx.push_back(x);
        uny.push_back(y);
      }
    }
    for (int i = 1; i <= n; i++) {
      if (!visit[i]) {
        topo(i);
      }
      adj[i].clear();
    }
    if (flag) {
      cout << "NO" << endl;
      continue;
    }
    reverse(toposort.begin(), toposort.end());
    for (int i = 0; i < toposort.size(); i++) {
      mp[toposort[i]] = i;
    }
    cout << "YES" << endl;
    for (int i = 0; i < dix.size(); i++) {
      cout << dix[i] << " " << diy[i] << endl;
    }
    for (int i = 0; i < unx.size(); i++) {
      if (mp[unx[i]] < mp[uny[i]]) {
        cout << unx[i] << " " << uny[i] << endl;
      } else {
        cout << uny[i] << " " << unx[i] << endl;
      }
    }
  }
}
