#include <bits/stdc++.h>

//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops")

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

#define f first
#define s second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define len(x) ((int)x.size())
#define pb push_back
//#define mp make_pair
#define lwb lower_bound
#define upb upper_bound
#define fch(elem, x) for (const auto &elem : x)
#define fchs(elem, x) for (auto &elem : x)

using namespace std;

void fast_io() {
    ios::sync_with_stdio(0);
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
}

void my_file_in_out() {
    freopen("inp.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
}

inline void OK(string t = "") { cerr << "OK " << t << '\n'; }
inline ld time() { return clock() / (ld)CLOCKS_PER_SEC; }
inline void stop(string t = "PROCESS FINISHED") { cerr << t << '\n'; exit(0); }

const ll MODD = 998244353;
const ll M = 1e9 + 7;

ll bp(ll c, ll st) {
    if (!st)
        return 1;
    if (st & 1)
        return (c * bp(c, st - 1)) % M;
    return bp((c * c) % M, st >> 1);
}

namespace VECTOR_MAGIC {
    template <typename T> istream &operator >>(istream &inp, vector <T>& a) {
        for (auto &elem : a)
            inp >> elem;
        return inp;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <T>& a) {
        for (auto &elem : a)
            out << elem << ' ';
        out << endl;
        return out;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <vector <T>>& a) {
        for (auto &elem : a)
            out << elem;
        return out;
    }
    template <typename T> void operator ++(vector <T> &a) {
        for (auto &el : a) el++;
    }
    template <typename T> void operator --(vector <T> &a) {
        for (auto &el : a) el--;
    }
}

using namespace VECTOR_MAGIC;

mt19937 rnd(time(0));

int rndc(int x) {
    int u = rnd();
    if (u < 0) u = -u;
    return u % x;
}

const int N = 3e5 + 7;
const int INF = 1e9 + 7;
const ll LINF = 4e17 + 9;

vector <vector <int>> g1, g2;
vector <int> used;
vector <pair <int, int>> edge;
bool flag;

void dfs1(int u, int p = -1) {
    used[u] = 1;
    fch (v, g1[u]) {
        if (v == p)
            continue;
        if (used[v]) {
            edge.push_back({v, u});
            continue;
        }
        edge.push_back({u, v});
        dfs1(v, u);
    }
}

void dfs2(int u) {
    used[u] = 1;
    fch (v, g2[u]) {
        if (used[v] == 2)
            continue;
        if (used[v] == 1) {
            flag = false;
            continue;
        }
        dfs2(v);
    }
    used[u] = 2;
}

void solve() {
    g1.clear();
    g2.clear();
    edge.clear();
    used.clear();
    int n, m;
    cin >> n >> m;
    g1.resize(n);
    g2.resize(n);
    vector <int> deg(n, 0);
    used.resize(n, 0);
    for (int i = 0; i < m; i++) {
        int t, u, v;
        cin >> t >> u >> v;
        u--; v--;
        if (t == 0) {
            g1[u].push_back(v);
            g1[v].push_back(u);
        } else {
            edge.push_back({u, v});
            deg[v]++;
        }
    }
    vector <int> way(n, 0);
    iota(all(way), 0);
    sort(all(way), [&](int u, int v) {
        return deg[u] < deg[v];
    });
    fchs (elem, g1) {
        sort(all(elem), [&](int u, int v) {
            return deg[u] > deg[v];
        });
    }
    fch (u, way)
        if (!used[u])
            dfs1(u);
    used.assign(n, 0);
    flag = true;
    fch (el, edge)
        g2[el.f].push_back(el.s);
    for (int i = 0; i < n; i++)
        if (used[i] == 0)
            dfs2(i);
    if (flag) {
        cout << "YES\n";
        fch (el, edge)
            cout << el.f + 1 << ' ' << el.s + 1 << '\n';
    } else {
        cout << "NO\n";
    }
}

signed main()
{
    fast_io();

    #ifdef LOCAL
        my_file_in_out();
    #endif

    int t = 1;
    cin >> t;

    while (t--)
        solve();

    #ifdef LOCAL
        cerr << "\n\n\ntime: " << time() << endl;
    #endif

    return 0;
}


#include <bits/stdc++.h>

//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops")

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

#define f first
#define s second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define len(x) ((int)x.size())
#define pb push_back
//#define mp make_pair
#define lwb lower_bound
#define upb upper_bound
#define fch(elem, x) for (const auto &elem : x)
#define fchs(elem, x) for (auto &elem : x)

using namespace std;

void fast_io() {
    ios::sync_with_stdio(0);
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
}

void my_file_in_out() {
    freopen("inp.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
}

inline void OK(string t = "") { cerr << "OK " << t << '\n'; }
inline ld time() { return clock() / (ld)CLOCKS_PER_SEC; }
inline void stop(string t = "PROCESS FINISHED") { cerr << t << '\n'; exit(0); }

const ll MODD = 998244353;
const ll M = 1e9 + 7;

ll bp(ll c, ll st) {
    if (!st)
        return 1;
    if (st & 1)
        return (c * bp(c, st - 1)) % M;
    return bp((c * c) % M, st >> 1);
}

namespace VECTOR_MAGIC {
    template <typename T> istream &operator >>(istream &inp, vector <T>& a) {
        for (auto &elem : a)
            inp >> elem;
        return inp;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <T>& a) {
        for (auto &elem : a)
            out << elem << ' ';
        out << endl;
        return out;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <vector <T>>& a) {
        for (auto &elem : a)
            out << elem;
        return out;
    }
    template <typename T> void operator ++(vector <T> &a) {
        for (auto &el : a) el++;
    }
    template <typename T> void operator --(vector <T> &a) {
        for (auto &el : a) el--;
    }
}

using namespace VECTOR_MAGIC;

mt19937 rnd(time(0));

int rndc(int x) {
    int u = rnd();
    if (u < 0) u = -u;
    return u % x;
}

const int N = 3e5 + 7;
const int INF = 1e9 + 7;
const ll LINF = 4e17 + 9;

vector <vector <int>> g1, g2;
vector <int> used;
vector <pair <int, int>> edge;
bool flag;

void dfs1(int u) {
    used[u] = 1;
    fch (v, g1[u]) {
        if (used[v])
            continue;
        edge.push_back({u, v});
        dfs1(v);
    }
}

void dfs2(int u) {
    used[u] = 1;
    fch (v, g2[u]) {
        if (used[v] == 2)
            continue;
        if (used[v] == 1) {
            flag = false;
            continue;
        }
        dfs2(v);
    }
    used[u] = 2;
}

void solve() {
    g1.clear();
    g2.clear();
    edge.clear();
    used.clear();
    int n, m;
    cin >> n >> m;
    g1.resize(n);
    g2.resize(n);
    vector <int> deg(n, 0);
    used.resize(n, 0);
    for (int i = 0; i < m; i++) {
        int t, u, v;
        cin >> t >> u >> v;
        u--; v--;
        if (t == 0) {
            g1[u].push_back(v);
            g1[v].push_back(u);
        } else {
            edge.push_back({u, v});
            deg[v]++;
        }
    }
    vector <int> way(n, 0);
    iota(all(way), 0);
    sort(all(way), [&](int u, int v) {
        return deg[u] < deg[v];
    });
    fchs (elem, g1) {
        sort(all(elem), [&](int u, int v) {
            return deg[u] < deg[v];
        });
    }
    fch (u, way)
        if (!used[u])
            dfs1(u);
    used.assign(n, 0);
    flag = true;
    fch (el, edge)
        g2[el.f].push_back(el.s);
    for (int i = 0; i < n; i++)
        if (used[i] == 0)
            dfs2(i);
    if (flag) {
        cout << "YES\n";
        fch (el, edge)
            cout << el.f + 1 << ' ' << el.s + 1 << '\n';
    } else {
        cout << "NO\n";
    }
}

signed main()
{
    fast_io();

    #ifdef LOCAL
        my_file_in_out();
    #endif

    int t = 1;
    cin >> t;

    while (t--)
        solve();

    #ifdef LOCAL
        cerr << "\n\n\ntime: " << time() << endl;
    #endif

    return 0;
}


#include <bits/stdc++.h>

//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops")

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

#define f first
#define s second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define len(x) ((int)x.size())
#define pb push_back
//#define mp make_pair
#define lwb lower_bound
#define upb upper_bound
#define fch(elem, x) for (const auto &elem : x)
#define fchs(elem, x) for (auto &elem : x)

using namespace std;

void fast_io() {
    ios::sync_with_stdio(0);
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
}

void my_file_in_out() {
    freopen("inp.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
}

inline void OK(string t = "") { cerr << "OK " << t << '\n'; }
inline ld time() { return clock() / (ld)CLOCKS_PER_SEC; }
inline void stop(string t = "PROCESS FINISHED") { cerr << t << '\n'; exit(0); }

const ll MODD = 998244353;
const ll M = 1e9 + 7;

ll bp(ll c, ll st) {
    if (!st)
        return 1;
    if (st & 1)
        return (c * bp(c, st - 1)) % M;
    return bp((c * c) % M, st >> 1);
}

namespace VECTOR_MAGIC {
    template <typename T> istream &operator >>(istream &inp, vector <T>& a) {
        for (auto &elem : a)
            inp >> elem;
        return inp;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <T>& a) {
        for (auto &elem : a)
            out << elem << ' ';
        out << endl;
        return out;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <vector <T>>& a) {
        for (auto &elem : a)
            out << elem;
        return out;
    }
    template <typename T> void operator ++(vector <T> &a) {
        for (auto &el : a) el++;
    }
    template <typename T> void operator --(vector <T> &a) {
        for (auto &el : a) el--;
    }
}

using namespace VECTOR_MAGIC;

mt19937 rnd(time(0));

int rndc(int x) {
    int u = rnd();
    if (u < 0) u = -u;
    return u % x;
}

const int N = 3e5 + 7;
const int INF = 1e9 + 7;
const ll LINF = 4e17 + 9;

vector <vector <int>> g1, g2;
vector <int> used;
vector <pair <int, int>> edge;
bool flag;

void dfs1(int u, int p = -1) {
    used[u] = 1;
    fch (v, g1[u]) {
        if (v == p)
            continue;
        if (used[v]) {
            edge.push_back({v, u});
            continue;
        }
        edge.push_back({u, v});
        dfs1(v, u);
    }
}

void dfs2(int u) {
    used[u] = 1;
    fch (v, g2[u]) {
        if (used[v] == 2)
            continue;
        if (used[v] == 1) {
            flag = false;
            continue;
        }
        dfs2(v);
    }
    used[u] = 2;
}

void solve() {
    g1.clear();
    g2.clear();
    edge.clear();
    used.clear();
    int n, m;
    cin >> n >> m;
    g1.resize(n);
    g2.resize(n);
    vector <int> deg(n, 0);
    used.resize(n, 0);
    for (int i = 0; i < m; i++) {
        int t, u, v;
        cin >> t >> u >> v;
        u--; v--;
        if (t == 0) {
            g1[u].push_back(v);
            g1[v].push_back(u);
        } else {
            edge.push_back({u, v});
            deg[v]++;
        }
    }
    vector <int> way(n, 0);
    iota(all(way), 0);
    sort(all(way), [&](int u, int v) {
        return deg[u] < deg[v];
    });
    fchs (elem, g1) {
        sort(all(elem), [&](int u, int v) {
            return deg[u] < deg[v];
        });
    }
    fch (u, way)
        if (!used[u])
            dfs1(u);
    used.assign(n, 0);
    flag = true;
    fch (el, edge)
        g2[el.f].push_back(el.s);
    for (int i = 0; i < n; i++)
        if (used[i] == 0)
            dfs2(i);
    if (flag) {
        cout << "YES\n";
        fch (el, edge)
            cout << el.f + 1 << ' ' << el.s + 1 << '\n';
    } else {
        cout << "NO\n";
    }
}

signed main()
{
    fast_io();

    #ifdef LOCAL
        my_file_in_out();
    #endif

    int t = 1;
    cin >> t;

    while (t--)
        solve();

    #ifdef LOCAL
        cerr << "\n\n\ntime: " << time() << endl;
    #endif

    return 0;
}


#include <bits/stdc++.h>

//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops")

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

#define f first
#define s second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define len(x) ((int)x.size())
#define pb push_back
//#define mp make_pair
#define lwb lower_bound
#define upb upper_bound
#define fch(elem, x) for (const auto &elem : x)
#define fchs(elem, x) for (auto &elem : x)

using namespace std;

void fast_io() {
    ios::sync_with_stdio(0);
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
}

void my_file_in_out() {
    freopen("inp.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
}

inline void OK(string t = "") { cerr << "OK " << t << '\n'; }
inline ld time() { return clock() / (ld)CLOCKS_PER_SEC; }
inline void stop(string t = "PROCESS FINISHED") { cerr << t << '\n'; exit(0); }

const ll MODD = 998244353;
const ll M = 1e9 + 7;

ll bp(ll c, ll st) {
    if (!st)
        return 1;
    if (st & 1)
        return (c * bp(c, st - 1)) % M;
    return bp((c * c) % M, st >> 1);
}

namespace VECTOR_MAGIC {
    template <typename T> istream &operator >>(istream &inp, vector <T>& a) {
        for (auto &elem : a)
            inp >> elem;
        return inp;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <T>& a) {
        for (auto &elem : a)
            out << elem << ' ';
        out << endl;
        return out;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <vector <T>>& a) {
        for (auto &elem : a)
            out << elem;
        return out;
    }
    template <typename T> void operator ++(vector <T> &a) {
        for (auto &el : a) el++;
    }
    template <typename T> void operator --(vector <T> &a) {
        for (auto &el : a) el--;
    }
}

using namespace VECTOR_MAGIC;

mt19937 rnd(time(0));

int rndc(int x) {
    int u = rnd();
    if (u < 0) u = -u;
    return u % x;
}

const int N = 3e5 + 7;
const int INF = 1e9 + 7;
const ll LINF = 4e17 + 9;

vector <vector <int>> g1, g2;
vector <int> used;
vector <pair <int, int>> edge;
bool flag;

void dfs1(int u) {
    used[u] = 1;
    fch (v, g1[u]) {
        if (used[v])
            continue;
        edge.push_back({u, v});
        dfs1(v);
    }
}

void dfs2(int u) {
    used[u] = 1;
    fch (v, g2[u]) {
        if (used[v] == 2)
            continue;
        if (used[v] == 1) {
            flag = false;
            continue;
        }
        dfs2(v);
    }
    used[u] = 2;
}

void solve() {
    g1.clear();
    g2.clear();
    edge.clear();
    used.clear();
    int n, m;
    cin >> n >> m;
    g1.resize(n);
    g2.resize(n);
    vector <int> deg(n, 0);
    used.resize(n, 0);
    for (int i = 0; i < m; i++) {
        int t, u, v;
        cin >> t >> u >> v;
        u--; v--;
        if (t == 0) {
            g1[u].push_back(v);
            g1[v].push_back(u);
        } else {
            edge.push_back({u, v});
            deg[v]++;
        }
    }
    vector <int> way(n, 0);
    iota(all(way), 0);
    sort(all(way), [&](int u, int v) {
        return deg[u] < deg[v];
    });
    fchs (elem, g1) {
        sort(all(elem), [&](int u, int v) {
            return deg[u] > deg[v];
        });
    }
    fch (u, way)
        if (!used[u])
            dfs1(u);
    used.assign(n, 0);
    flag = true;
    fch (el, edge)
        g2[el.f].push_back(el.s);
    for (int i = 0; i < n; i++)
        if (used[i] == 0)
            dfs2(i);
    if (flag) {
        cout << "YES\n";
        fch (el, edge)
            cout << el.f + 1 << ' ' << el.s + 1 << '\n';
    } else {
        cout << "NO\n";
    }
}

signed main()
{
    fast_io();

    #ifdef LOCAL
        my_file_in_out();
    #endif

    int t = 1;
    cin >> t;

    while (t--)
        solve();

    #ifdef LOCAL
        cerr << "\n\n\ntime: " << time() << endl;
    #endif

    return 0;
}


#include <bits/stdc++.h>

//#pragma GCC optimize("Ofast,no-stack-protector,unroll-loops")

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

#define f first
#define s second
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define len(x) ((int)x.size())
#define pb push_back
//#define mp make_pair
#define lwb lower_bound
#define upb upper_bound
#define fch(elem, x) for (const auto &elem : x)
#define fchs(elem, x) for (auto &elem : x)

using namespace std;

void fast_io() {
    ios::sync_with_stdio(0);
    ios_base::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
}

void my_file_in_out() {
    freopen("inp.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
}

inline void OK(string t = "") { cerr << "OK " << t << '\n'; }
inline ld time() { return clock() / (ld)CLOCKS_PER_SEC; }
inline void stop(string t = "PROCESS FINISHED") { cerr << t << '\n'; exit(0); }

const ll MODD = 998244353;
const ll M = 1e9 + 7;

ll bp(ll c, ll st) {
    if (!st)
        return 1;
    if (st & 1)
        return (c * bp(c, st - 1)) % M;
    return bp((c * c) % M, st >> 1);
}

namespace VECTOR_MAGIC {
    template <typename T> istream &operator >>(istream &inp, vector <T>& a) {
        for (auto &elem : a)
            inp >> elem;
        return inp;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <T>& a) {
        for (auto &elem : a)
            out << elem << ' ';
        out << endl;
        return out;
    }
    template <typename T> ostream &operator <<(ostream &out, vector <vector <T>>& a) {
        for (auto &elem : a)
            out << elem;
        return out;
    }
    template <typename T> void operator ++(vector <T> &a) {
        for (auto &el : a) el++;
    }
    template <typename T> void operator --(vector <T> &a) {
        for (auto &el : a) el--;
    }
}

using namespace VECTOR_MAGIC;

mt19937 rnd(time(0));

int rndc(int x) {
    int u = rnd();
    if (u < 0) u = -u;
    return u % x;
}

const int N = 3e5 + 7;
const int INF = 1e9 + 7;
const ll LINF = 4e17 + 9;

vector <vector <int>> g;
vector <int> used;
vector <int> ord;
bool flag;

void dfs(int u) {
    used[u] = 1;
    fch (v, g[u]) {
        if (used[v] == 2)
            continue;
        if (used[v] == 1) {
            flag = false;
            continue;
        }
        dfs(v);
    }
    ord.push_back(u);
    used[u] = 2;
}

void solve() {
    g.clear();
    ord.clear();
    used.clear();
    int n, m;
    cin >> n >> m;
    g.resize(n);
    used.resize(n, 0);
    vector <pair <int, int>> edg, ans;
    for (int i = 0; i < m; i++) {
        int t, u, v;
        cin >> t >> u >> v;
        u--; v--;
        if (t == 0) {
            edg.push_back({u, v});
        } else {
            ans.push_back({u, v});
            g[u].push_back(v);
        }
    }
    vector <int> way(n, 0);
    iota(all(way), 0);
    flag = true;
    fch (u, way)
        if (!used[u])
            dfs(u);
    reverse(all(ord));
    for (int i = 0; i < n; i++)
        way[ord[i]] = i;
    fchs (el, edg) {
        if (way[el.f] > way[el.s])
            swap(el.f, el.s);
        ans.push_back(el);
    }
    if (flag) {
        cout << "YES\n";
        fch (el, ans)
            cout << el.f + 1 << ' ' << el.s + 1 << '\n';
    } else {
        cout << "NO\n";
    }
}

signed main()
{
    fast_io();

    #ifdef LOCAL
        my_file_in_out();
    #endif

    int t = 1;
    cin >> t;

    while (t--)
        solve();

    #ifdef LOCAL
        cerr << "\n\n\ntime: " << time() << endl;
    #endif

    return 0;
}


// Khud ke baski to hai nai
    // isliye yaha dekhne aa gaye

//https://github.com/rafi-kamal/ACM-Solutions/blob/master/LightOj/String/1255%20-%20Substring%20Frequency.cpp

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;
void fast();
#define print(a)        for (auto x : a) cout << x << " "; cout << endl
#define print_upto(a,n)        for(int i=0;i<n;i++)    cout<<a[i]<<" "; cout<<endl
#define take(x,n)           for(int i=0;i<n;i++)  cin>>x[i];
#define rep(i,n)        for(int i=0;i<n;i++)
#define repange(i,a,b)      for(int i=a;i<=b;i++)
#define reprange(i,a,b)     for(int i=a;i>=b;i--)
#define okay    cout << "okay" << endl
#define hey     cout << "hey" << endl
#define ll long long
#define ull unsigned long long
#define ldob long double
#define dob double
#define F first
#define S second
#define pii pair<int, int>
#define vec(a) vector<a>
#define umap(a, b) unordered_map<a, b>
#define endl "\n"
#define inf 1e18
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define mem(a,b) memset(a,b,sizeof(a))

//======================================================================================//

clock_t time_p=clock();
void TTIIMMEE()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}

const int RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash {
    int operator()(int x) const { return x ^ RANDOM; }
}; // datatype ki jagah gp_hash_table<key_type,int,chash> , for eg : Dp like hashmap : vector<gp_hash_table<int,int,chash>>dp(N);

//======================================================================================//
#define MOD 1000000007
int mod=1000000007;
#define int long long int
#define N 200005
int ar[N];
int n,a,b,c,d,m,k,q,t,x;
vec(int) v;

set<pii> ans;

ll modexp(ll x, ll n,ll mod){ if(n==0)return 1; else if(n&1){return (modexp((x*x)%mod, n/2,mod)%mod * x%mod)%mod;}else{return (modexp((x*x)%mod, n/2,mod)%mod);}}
int modInverse(int n, int p) { return modexp(n, p-2, p); }
inline int add(int x,int y) {  return (x%mod + y%mod + mod)%mod; }
inline int mul(int x,int y) {  return (x%mod * y%mod + mod)%mod; }
inline int sub(int x,int y) {  return (x%mod - y%mod + mod)%mod; }

// Class to represent a graph
class Graph
{
// No. of vertices'
    int V;

    // Pointer to an array containing adjacency listsList
    list<int> *adj;

    // A function used by topologicalSort
    void topologicalSortUtil(int v, bool visited[],
 stack<int> &Stack);
    bool isCyclicUtil(int v, bool visited[], bool *rs);  // used by isCyclic()
public:
// Constructor
    Graph(int V);

     // function to add an edge to graph
    void addEdge(int v, int w);

    // prints a Topological Sort of
// the complete graph
    void topologicalSort();
    bool isCyclic();    // returns true if there is a cycle in this graph
};

Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)
{
// Add w to v’s list.
    adj[v].push_back(w);
}

// A recursive function used by topologicalSort
void Graph::topologicalSortUtil(
int v, bool visited[],
                                stack<int> &Stack)
{
    // Mark the current node as visited.
    visited[v] = true;

    // Recur for all the vertices
// adjacent to this vertex
    list<int>::iterator i;
    for (i = adj[v].begin(); i != adj[v].end(); ++i)
        if (!visited[*i] && ans.find({*i,v})==ans.end()) {
            ans.insert({v,*i});
            topologicalSortUtil(*i, visited, Stack);
        }

    // Push current vertex to stack
// which stores result
    Stack.push(v);
}

// The function to do Topological Sort.
// It uses recursive topologicalSortUtil()
void Graph::topologicalSort()
{
    stack<int> Stack;

    // Mark all the vertices as not visited
    bool *visited = new bool[V];
    for (int i = 0; i < V; i++)
        visited[i] = false;

    // Call the recursive helper function
// to store Topological
    // Sort starting from all
// vertices one by one
    for (int i = 0; i < V; i++)
      if (visited[i] == false)
        topologicalSortUtil(i, visited, Stack);

    // Print contents of stack
    while (Stack.empty() == false)
    {
        //cout << Stack.top() << " ";
        Stack.pop();
    }
}

bool flag = true;

bool Graph::isCyclicUtil(int v, bool visited[], bool *recStack)
{
    if(visited[v] == false)
    {
        // Mark the current node as visited and part of recursion stack
        visited[v] = true;
        recStack[v] = true;

        // Recur for all the vertices adjacent to this vertex
        list<int>::iterator i;
        for(i = adj[v].begin(); i != adj[v].end(); ++i)
        {
            if ( !visited[*i] && isCyclicUtil(*i, visited, recStack) )
                return true;
            else if (recStack[*i])
                return true;
        }

    }
    recStack[v] = false;  // remove the vertex from recursion stack
    return false;
}

// Returns true if the graph contains a cycle, else false.
// This function is a variation of DFS() in https://www.geeksforgeeks.org/archives/18212
bool Graph::isCyclic()
{
    // Mark all the vertices as not visited and not part of recursion
    // stack
    bool *visited = new bool[V];
    bool *recStack = new bool[V];
    for(int i = 0; i < V; i++)
    {
        visited[i] = false;
        recStack[i] = false;
    }

    // Call the recursive helper function to detect cycle in different
    // DFS trees
    for(int i = 0; i < V; i++)
        if (isCyclicUtil(i, visited, recStack))
            return true;

    return false;
}

int32_t main()
{
    fast();

    int testcase=1;    //change t if required
    cin>>testcase;
    while(testcase--)
    {
        ans.clear();
        cin>>n>>m;
        Graph g(n+1);
        Graph g1(n+1);

        vec(pii) alledge;

        rep(i,m)
        {
            cin>>a>>b>>c;
            alledge.pb({b,c});
            if(a==1){
                ans.insert({b,c});
                g.addEdge(b,c);
                g1.addEdge(b,c);
            }
            else
            {
                g.addEdge(b, c);
                g.addEdge(c, b);
            }
        }

        if(g1.isCyclic())
        {
            cout<<"NO"<<endl;
            continue;
        }
        g.topologicalSort();

        if(!flag)
        {
            cout<<"NO"<<endl;
            continue;
        }

        if(flag)
            cout<<"YES"<<endl;

        for(auto it:alledge)
        {
            if(ans.find(it)==ans.end())
            {
                cout<<it.S<<" "<<it.F<<endl;
            }
            else
            {
                cout<<it.F<<" "<<it.S<<endl;
            }
        }

    }
    TTIIMMEE();
    return 0;
}

void fast()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}


// Khud ke baski to hai nai
    // isliye yaha dekhne aa gaye

//https://github.com/rafi-kamal/ACM-Solutions/blob/master/LightOj/String/1255%20-%20Substring%20Frequency.cpp

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;
void fast();
#define print(a)        for (auto x : a) cout << x << " "; cout << endl
#define print_upto(a,n)        for(int i=0;i<n;i++)    cout<<a[i]<<" "; cout<<endl
#define take(x,n)           for(int i=0;i<n;i++)  cin>>x[i];
#define rep(i,n)        for(int i=0;i<n;i++)
#define repange(i,a,b)      for(int i=a;i<=b;i++)
#define reprange(i,a,b)     for(int i=a;i>=b;i--)
#define okay    cout << "okay" << endl
#define hey     cout << "hey" << endl
#define ll long long
#define ull unsigned long long
#define ldob long double
#define dob double
#define F first
#define S second
#define pii pair<int, int>
#define vec(a) vector<a>
#define umap(a, b) unordered_map<a, b>
#define endl "\n"
#define inf 1e18
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define mem(a,b) memset(a,b,sizeof(a))

//======================================================================================//

clock_t time_p=clock();
void TTIIMMEE()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}

const int RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash {
    int operator()(int x) const { return x ^ RANDOM; }
}; // datatype ki jagah gp_hash_table<key_type,int,chash> , for eg : Dp like hashmap : vector<gp_hash_table<int,int,chash>>dp(N);

//======================================================================================//
#define MOD 1000000007
int mod=1000000007;
#define int long long int
#define N 200005
int ar[N];
int n,a,b,c,d,m,k,q,t,x;
vec(int) v;

ll modexp(ll x, ll n,ll mod){ if(n==0)return 1; else if(n&1){return (modexp((x*x)%mod, n/2,mod)%mod * x%mod)%mod;}else{return (modexp((x*x)%mod, n/2,mod)%mod);}}
int modInverse(int n, int p) { return modexp(n, p-2, p); }
inline int add(int x,int y) {  return (x%mod + y%mod + mod)%mod; }
inline int mul(int x,int y) {  return (x%mod * y%mod + mod)%mod; }
inline int sub(int x,int y) {  return (x%mod - y%mod + mod)%mod; }

// void bfs(int start,list<pii>adj[],set<pii>ans)
// {
//     queue<int>q;
//     int visited[N];

//     set<pii>done;
//     q.push(start);
//     visited[start]=1;

//     while(!q.empty())
//     {
//         int node = q.front();
//         q.pop();

//         //cout<<"aaya "<<node<<endl;

//         for(auto it:adj[node])
//         {
//             if(visited[it.F]==0)
//             {
//                 q.push(it.F);
//                 visited[it.F]=1;
//             }

//             if(it.S==0 && done.find({it.F,node})==done.end())
//             {
//                 ans.insert({it.F,node});
//                 it.S = -1;
//                 done.insert({node,it.F});
//             }
//         }
//     }

//     for(auto it:ans)
//     {
//         cout<<it.F<<" "<<it.S<<endl;
//     }

// }

int out[N];
int32_t main()
{
    fast();

    int testcase=1;    //change t if required
    cin>>testcase;
    while(testcase--)
    {
        set<pii>ans;
        cin>>n>>m;
        rep(i,n+1) out[i]=0;
        list<pii>adj[N];

        set<int>ele;
        rep(i,m)
        {
            cin>>a>>b>>c;
            ele.insert(b);
            ele.insert(c);
            if(a==1){
                ans.insert({b,c});

                adj[b].pb({c,1});
                adj[c].pb({b,-1});
                out[b]++;
            }
            else
            {
                adj[b].pb({c,0});
                adj[c].pb({b,0});
            }
        }

        int start = 0;
        for(auto it:ele)
        {

            if(out[it]==0) start = it;
        }

        if(start==0)
        {
            cout<<"NO"<<endl;
        }
        else
        {
            cout<<"YES"<<endl;

            ///BFS

            queue<int>q;
            int visited[n+1];
            mem(visited,0);

            set<pii>done;
            q.push(start);
            visited[start]=1;

            while(!q.empty())
            {
                int node = q.front();
                q.pop();

                //cout<<"aaya "<<node<<endl;

                for(auto it:adj[node])
                {
                    if(visited[it.F]==0)
                    {
                        q.push(it.F);
                        visited[it.F]=1;
                    }

                    if(it.S==0 && done.find({it.F,node})==done.end())
                    {
                        ans.insert({it.F,node});
                        //cout<<"ans size = "<<ans.size()<<endl;
                        it.S = -1;
                        done.insert({node,it.F});
                    }
                }
            }

            for(auto it:ans)
            {
                cout<<it.F<<" "<<it.S<<endl;
            }
        }

    }
    TTIIMMEE();
    return 0;
}

void fast()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}


// Khud ke baski to hai nai
    // isliye yaha dekhne aa gaye

//https://github.com/rafi-kamal/ACM-Solutions/blob/master/LightOj/String/1255%20-%20Substring%20Frequency.cpp

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;
void fast();
#define print(a)        for (auto x : a) cout << x << " "; cout << endl
#define print_upto(a,n)        for(int i=0;i<n;i++)    cout<<a[i]<<" "; cout<<endl
#define take(x,n)           for(int i=0;i<n;i++)  cin>>x[i];
#define rep(i,n)        for(int i=0;i<n;i++)
#define repange(i,a,b)      for(int i=a;i<=b;i++)
#define reprange(i,a,b)     for(int i=a;i>=b;i--)
#define okay    cout << "okay" << endl
#define hey     cout << "hey" << endl
#define ll long long
#define ull unsigned long long
#define ldob long double
#define dob double
#define F first
#define S second
#define pii pair<int, int>
#define vec(a) vector<a>
#define umap(a, b) unordered_map<a, b>
#define endl "\n"
#define inf 1e18
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define mem(a,b) memset(a,b,sizeof(a))

//======================================================================================//

// typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;  // ordered_set   cout << *(o_set.find_by_order(1))  and cout << o_set.order_of_key(4)
// template <class T> ostream& operator << (ostream &os, const vector<T> &v) { for (T i : v) os << i << ", "; return os; }
// template <class T> ostream& operator << (ostream &os, const set<T> &v) { for (T i : v) os << i << " "; return os; }
// template <class T> ostream& operator << (ostream &os, const multiset<T> &v) { for (T i : v) os << i << " "; return os; }
// template <class T, class S> ostream& operator << (ostream &os, const pair<T, S> &v) { os << v.F << ' ' << v.S; return os; }
// template <class T, class S> ostream& operator << (ostream &os, const map<T, S> &v) { for (auto i : v) os << '(' << i.F << " => " << i.S << ')' << ' '; return os; }

// typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>ordered_set;

// #ifndef ONLINE_JUDGE
// #define trace(...) _f(#VA_ARGS, __VA_ARGS_)
//     template <class Arg1> void __f(const char* name, Arg1&& arg1) { cerr << name << " : " << arg1 << endl; }
//     template <class Arg1, class... Args>
//     void __f(const char* names, Arg1&& arg1, Args&&... args) {
//         const char* sep = strchr(names + 1, ',');
//         cerr.write(names, sep - names) << " : " << arg1 << "  ";
//         __f(sep + 1, args...);
//     }
// #else
// #define trace(...) 0
// #pragma GCC optimize ("O3")
// #pragma GCC optimize ("unroll-loops")
// #pragma GCC target("avx2,sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
// #define _CRT_SECURE_NO_WARNINGS
// #endif // ifndef ONLINE_JUDGE

clock_t time_p=clock();
void TTIIMMEE()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}

const int RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash {
    int operator()(int x) const { return x ^ RANDOM; }
}; // datatype ki jagah gp_hash_table<key_type,int,chash> , for eg : Dp like hashmap : vector<gp_hash_table<int,int,chash>>dp(N);

//======================================================================================//
#define MOD 1000000007
int mod=1000000007;
#define int long long int
#define N 200005
int ar[N];
int n,a,b,c,d,m,k,q,t,x;
vec(int) v;

ll modexp(ll x, ll n,ll mod){ if(n==0)return 1; else if(n&1){return (modexp((x*x)%mod, n/2,mod)%mod * x%mod)%mod;}else{return (modexp((x*x)%mod, n/2,mod)%mod);}}
int modInverse(int n, int p) { return modexp(n, p-2, p); }
inline int add(int x,int y) {  return (x%mod + y%mod + mod)%mod; }
inline int mul(int x,int y) {  return (x%mod * y%mod + mod)%mod; }
inline int sub(int x,int y) {  return (x%mod - y%mod + mod)%mod; }

// void bfs(int start,list<pii>adj[],set<pii>ans)
// {
//     queue<int>q;
//     int visited[N];

//     set<pii>done;
//     q.push(start);
//     visited[start]=1;

//     while(!q.empty())
//     {
//         int node = q.front();
//         q.pop();

//         //cout<<"aaya "<<node<<endl;

//         for(auto it:adj[node])
//         {
//             if(visited[it.F]==0)
//             {
//                 q.push(it.F);
//                 visited[it.F]=1;
//             }

//             if(it.S==0 && done.find({it.F,node})==done.end())
//             {
//                 ans.insert({it.F,node});
//                 it.S = -1;
//                 done.insert({node,it.F});
//             }
//         }
//     }

//     for(auto it:ans)
//     {
//         cout<<it.F<<" "<<it.S<<endl;
//     }

// }

int32_t main()
{
    fast();

    int testcase=1;    //change t if required
    cin>>testcase;
    while(testcase--)
    {
        set<pii>ans;
        cin>>n>>m;
        int out[n+1];
        mem(out,0);
        list<pii>adj[n+1];

        rep(i,m)
        {
            cin>>a>>b>>c;

            if(a==1){
                ans.insert({b,c});

                adj[b].pb({c,1});
                adj[c].pb({b,-1});
                out[b]++;
            }
            else
            {
                adj[b].pb({c,0});
                adj[c].pb({b,0});
            }
        }

        int start = 0;
        rep(i,n)
        {
            if(out[i+1]==0) start = i+1;
        }

        if(start==0)
        {
            cout<<"NO"<<endl;
        }
        else
        {
            cout<<"YES"<<endl;

            ///BFS

            queue<int>q;
            int visited[N];

            set<pii>done;
            q.push(start);
            visited[start]=1;

            while(!q.empty())
            {
                int node = q.front();
                q.pop();

                //cout<<"aaya "<<node<<endl;

                for(auto it:adj[node])
                {
                    if(visited[it.F]==0)
                    {
                        q.push(it.F);
                        visited[it.F]=1;
                    }

                    if(it.S==0 && done.find({it.F,node})==done.end())
                    {
                        ans.insert({it.F,node});
                        it.S = -1;
                        done.insert({node,it.F});
                    }
                }
            }

            for(auto it:ans)
            {
                cout<<it.F<<" "<<it.S<<endl;
            }
        }

    }
    TTIIMMEE();
    return 0;
}

void fast()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}


    // Khud ke baski to hai nai
    // isliye yaha dekhne aa gaye

//https://github.com/rafi-kamal/ACM-Solutions/blob/master/LightOj/String/1255%20-%20Substring%20Frequency.cpp

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;
void fast();
#define print(a)        for (auto x : a) cout << x << " "; cout << endl
#define print_upto(a,n)        for(int i=0;i<n;i++)    cout<<a[i]<<" "; cout<<endl
#define take(x,n)           for(int i=0;i<n;i++)  cin>>x[i];
#define rep(i,n)        for(int i=0;i<n;i++)
#define repange(i,a,b)      for(int i=a;i<=b;i++)
#define reprange(i,a,b)     for(int i=a;i>=b;i--)
#define okay    cout << "okay" << endl
#define hey     cout << "hey" << endl
#define ll long long
#define ull unsigned long long
#define ldob long double
#define dob double
#define F first
#define S second
#define pii pair<int, int>
#define vec(a) vector<a>
#define umap(a, b) unordered_map<a, b>
#define endl "\n"
#define inf 1e18
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define mem(a,b) memset(a,b,sizeof(a))

//======================================================================================//

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;  // ordered_set   cout << *(o_set.find_by_order(1))  and cout << o_set.order_of_key(4)
template <class T> ostream& operator << (ostream &os, const vector<T> &v) { for (T i : v) os << i << ", "; return os; }
template <class T> ostream& operator << (ostream &os, const set<T> &v) { for (T i : v) os << i << " "; return os; }
template <class T> ostream& operator << (ostream &os, const multiset<T> &v) { for (T i : v) os << i << " "; return os; }
template <class T, class S> ostream& operator << (ostream &os, const pair<T, S> &v) { os << v.F << ' ' << v.S; return os; }
template <class T, class S> ostream& operator << (ostream &os, const map<T, S> &v) { for (auto i : v) os << '(' << i.F << " => " << i.S << ')' << ' '; return os; }

typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>ordered_set;

#ifndef ONLINE_JUDGE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <class Arg1> void __f(const char* name, Arg1&& arg1) { cerr << name << " : " << arg1 << endl; }
    template <class Arg1, class... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args) {
        const char* sep = strchr(names + 1, ',');
        cerr.write(names, sep - names) << " : " << arg1 << "  ";
        __f(sep + 1, args...);
    }
#else
#define trace(...) 0
#pragma GCC optimize ("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx2,sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define _CRT_SECURE_NO_WARNINGS
#endif // ifndef ONLINE_JUDGE

clock_t time_p=clock();
void TTIIMMEE()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}

const int RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash {
    int operator()(int x) const { return x ^ RANDOM; }
}; // datatype ki jagah gp_hash_table<key_type,int,chash> , for eg : Dp like hashmap : vector<gp_hash_table<int,int,chash>>dp(N);

//======================================================================================//
#define MOD 1000000007
int mod=1000000007;
#define int long long int
#define N 200005
int ar[N];
int n,a,b,c,d,m,k,q,t,x;
vec(int) v;

ll modexp(ll x, ll n,ll mod){ if(n==0)return 1; else if(n&1){return (modexp((x*x)%mod, n/2,mod)%mod * x%mod)%mod;}else{return (modexp((x*x)%mod, n/2,mod)%mod);}}
int modInverse(int n, int p) { return modexp(n, p-2, p); }
inline int add(int x,int y) {  return (x%mod + y%mod + mod)%mod; }
inline int mul(int x,int y) {  return (x%mod * y%mod + mod)%mod; }
inline int sub(int x,int y) {  return (x%mod - y%mod + mod)%mod; }

bool is_cyclic(int cur,list<int>adj[],int visited[])
{
    visited[cur] = 1;

    for(auto it:adj[cur])
    {
        if(visited[it]==1) return true;
        if(visited[it]==0 && is_cyclic(it,adj,visited)) return true;
    }

    visited[cur]=2;
    return false;
}

int32_t main()
{
    fast();

    int testcase=1;    //change t if required
    cin>>testcase;
    while(testcase--)
    {
        cin>>n>>m;
        int indeg[n+1];
        mem(indeg,0);

        vec(pii) one,zero;
        list<int>adj[n+1];

        rep(i,m)
        {
            cin>>a>>b>>c;
            if(a==0)
                zero.pb({b,c});

            else
            {
                one.pb({b,c});
                indeg[c]++;
                adj[b].pb(c);
            }
        }

        int visited[n+1];
        mem(visited,0);
        int f=0;
        for(int i=1;i<=n;i++)
        {
            if(!visited[i])
                if(is_cyclic(i,adj,visited)){
                    f=1;
                    break;
                }
        }

        if(f)
        {
            cout<<"NO"<<endl;
            continue;
        }

        cout<<"YES"<<endl;
        queue<int>q;
        vec(int) ans;
        rep(i,n+1)
        {
            if(indeg[i+1]==0){
                q.push(i+1);
                ans.pb(i+1);
            }
        }

        while(!q.empty())
        {
            int temp = q.front();
            q.pop();

            for(auto it:adj[temp])
            {
                indeg[it]--;
                if(indeg[it]==0) q.push(it),ans.pb(it);
            }
        }

        map<int,int>mp;
        int ptr = 0;

        for(auto it:ans)
            mp[it]=ptr++;

        for(auto it:one)
        {
            cout<<it.F<<" "<<it.S<<endl;
        }
        for(auto it:zero)
        {
            if(mp[it.F]<mp[it.S])
                cout<<it.F<<" "<<it.S<<endl;
            else cout<<it.S<<" "<<it.F<<endl;
        }
    }
    TTIIMMEE();
    return 0;
}

void fast()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}


// Khud ke baski to hai nai
    // isliye yaha dekhne aa gaye

//https://github.com/rafi-kamal/ACM-Solutions/blob/master/LightOj/String/1255%20-%20Substring%20Frequency.cpp

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;
void fast();
#define print(a)        for (auto x : a) cout << x << " "; cout << endl
#define print_upto(a,n)        for(int i=0;i<n;i++)    cout<<a[i]<<" "; cout<<endl
#define take(x,n)           for(int i=0;i<n;i++)  cin>>x[i];
#define rep(i,n)        for(int i=0;i<n;i++)
#define repange(i,a,b)      for(int i=a;i<=b;i++)
#define reprange(i,a,b)     for(int i=a;i>=b;i--)
#define okay    cout << "okay" << endl
#define hey     cout << "hey" << endl
#define ll long long
#define ull unsigned long long
#define ldob long double
#define dob double
#define F first
#define S second
#define pii pair<int, int>
#define vec(a) vector<a>
#define umap(a, b) unordered_map<a, b>
#define endl "\n"
#define inf 1e18
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define mem(a,b) memset(a,b,sizeof(a))

//======================================================================================//

clock_t time_p=clock();
void TTIIMMEE()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}

const int RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash {
    int operator()(int x) const { return x ^ RANDOM; }
}; // datatype ki jagah gp_hash_table<key_type,int,chash> , for eg : Dp like hashmap : vector<gp_hash_table<int,int,chash>>dp(N);

//======================================================================================//
#define MOD 1000000007
int mod=1000000007;
#define int long long int
#define N 200005
int ar[N];
int n,a,b,c,d,m,k,q,t,x;
vec(int) v;

set<pii> ans;

ll modexp(ll x, ll n,ll mod){ if(n==0)return 1; else if(n&1){return (modexp((x*x)%mod, n/2,mod)%mod * x%mod)%mod;}else{return (modexp((x*x)%mod, n/2,mod)%mod);}}
int modInverse(int n, int p) { return modexp(n, p-2, p); }
inline int add(int x,int y) {  return (x%mod + y%mod + mod)%mod; }
inline int mul(int x,int y) {  return (x%mod * y%mod + mod)%mod; }
inline int sub(int x,int y) {  return (x%mod - y%mod + mod)%mod; }

// Class to represent a graph
class Graph
{
// No. of vertices'
    int V;

    // Pointer to an array containing adjacency listsList
    list<int> *adj;

    // A function used by topologicalSort
    void topologicalSortUtil(int v, bool visited[],
 stack<int> &Stack);
    bool isCyclicUtil(int v, bool visited[], bool *rs);  // used by isCyclic()
public:
// Constructor
    Graph(int V);

     // function to add an edge to graph
    void addEdge(int v, int w);

    // prints a Topological Sort of
// the complete graph
    void topologicalSort();
    bool isCyclic();    // returns true if there is a cycle in this graph
};

Graph::Graph(int V)
{
    this->V = V;
    adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)
{
// Add w to v’s list.
    adj[v].push_back(w);
}

// A recursive function used by topologicalSort
void Graph::topologicalSortUtil(
int v, bool visited[],
                                stack<int> &Stack)
{
    // Mark the current node as visited.
    visited[v] = true;

    // Recur for all the vertices
// adjacent to this vertex
    list<int>::iterator i;
    for (i = adj[v].begin(); i != adj[v].end(); ++i)
        if (!visited[*i]) {
            ans.insert({v,*i});
            topologicalSortUtil(*i, visited, Stack);
        }

    // Push current vertex to stack
// which stores result
    Stack.push(v);
}

// The function to do Topological Sort.
// It uses recursive topologicalSortUtil()
void Graph::topologicalSort()
{
    stack<int> Stack;

    // Mark all the vertices as not visited
    bool *visited = new bool[V];
    for (int i = 0; i < V; i++)
        visited[i] = false;

    // Call the recursive helper function
// to store Topological
    // Sort starting from all
// vertices one by one
    for (int i = 0; i < V; i++)
      if (visited[i] == false)
        topologicalSortUtil(i, visited, Stack);

    // Print contents of stack
    while (Stack.empty() == false)
    {
        //cout << Stack.top() << " ";
        Stack.pop();
    }
}

bool flag = true;

bool Graph::isCyclicUtil(int v, bool visited[], bool *recStack)
{
    if(visited[v] == false)
    {
        // Mark the current node as visited and part of recursion stack
        visited[v] = true;
        recStack[v] = true;

        // Recur for all the vertices adjacent to this vertex
        list<int>::iterator i;
        for(i = adj[v].begin(); i != adj[v].end(); ++i)
        {
            if ( !visited[*i] && isCyclicUtil(*i, visited, recStack) )
                return true;
            else if (recStack[*i])
                return true;
        }

    }
    recStack[v] = false;  // remove the vertex from recursion stack
    return false;
}

// Returns true if the graph contains a cycle, else false.
// This function is a variation of DFS() in https://www.geeksforgeeks.org/archives/18212
bool Graph::isCyclic()
{
    // Mark all the vertices as not visited and not part of recursion
    // stack
    bool *visited = new bool[V];
    bool *recStack = new bool[V];
    for(int i = 0; i < V; i++)
    {
        visited[i] = false;
        recStack[i] = false;
    }

    // Call the recursive helper function to detect cycle in different
    // DFS trees
    for(int i = 0; i < V; i++)
        if (isCyclicUtil(i, visited, recStack))
            return true;

    return false;
}

int32_t main()
{
    fast();

    int testcase=1;    //change t if required
    cin>>testcase;
    while(testcase--)
    {
        ans.clear();
        cin>>n>>m;
        Graph g(n+1);
        Graph g1(n+1);

        vec(pii) alledge;

        rep(i,m)
        {
            cin>>a>>b>>c;
            alledge.pb({b,c});
            if(a==1){
                g.addEdge(b,c);
                g1.addEdge(b,c);
            }
            else
            {
                g.addEdge(b, c);
                g.addEdge(c, b);
            }
        }

        if(g1.isCyclic())
        {
            cout<<"NO"<<endl;
            continue;
        }
        g.topologicalSort();

        if(!flag)
        {
            cout<<"NO"<<endl;
            continue;
        }

        if(flag)
            cout<<"YES"<<endl;

        for(auto it:alledge)
        {
            if(ans.find(it)==ans.end())
            {
                cout<<it.S<<" "<<it.F<<endl;
            }
            else
            {
                cout<<it.F<<" "<<it.S<<endl;
            }
        }

    }
    TTIIMMEE();
    return 0;
}

void fast()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}


    // Khud ke baski to hai nai
    // isliye yaha dekhne aa gaye

//https://github.com/rafi-kamal/ACM-Solutions/blob/master/LightOj/String/1255%20-%20Substring%20Frequency.cpp

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;
void fast();
#define print(a)        for (auto x : a) cout << x << " "; cout << endl
#define print_upto(a,n)        for(int i=0;i<n;i++)    cout<<a[i]<<" "; cout<<endl
#define take(x,n)           for(int i=0;i<n;i++)  cin>>x[i];
#define rep(i,n)        for(int i=0;i<n;i++)
#define repange(i,a,b)      for(int i=a;i<=b;i++)
#define reprange(i,a,b)     for(int i=a;i>=b;i--)
#define okay    cout << "okay" << endl
#define hey     cout << "hey" << endl
#define ll long long
#define ull unsigned long long
#define ldob long double
#define dob double
#define F first
#define S second
#define pii pair<int, int>
#define vec(a) vector<a>
#define umap(a, b) unordered_map<a, b>
#define endl "\n"
#define inf 1e18
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define mem(a,b) memset(a,b,sizeof(a))

//======================================================================================//

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;  // ordered_set   cout << *(o_set.find_by_order(1))  and cout << o_set.order_of_key(4)
template <class T> ostream& operator << (ostream &os, const vector<T> &v) { for (T i : v) os << i << ", "; return os; }
template <class T> ostream& operator << (ostream &os, const set<T> &v) { for (T i : v) os << i << " "; return os; }
template <class T> ostream& operator << (ostream &os, const multiset<T> &v) { for (T i : v) os << i << " "; return os; }
template <class T, class S> ostream& operator << (ostream &os, const pair<T, S> &v) { os << v.F << ' ' << v.S; return os; }
template <class T, class S> ostream& operator << (ostream &os, const map<T, S> &v) { for (auto i : v) os << '(' << i.F << " => " << i.S << ')' << ' '; return os; }

typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>ordered_set;

#ifndef ONLINE_JUDGE
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
    template <class Arg1> void __f(const char* name, Arg1&& arg1) { cerr << name << " : " << arg1 << endl; }
    template <class Arg1, class... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args) {
        const char* sep = strchr(names + 1, ',');
        cerr.write(names, sep - names) << " : " << arg1 << "  ";
        __f(sep + 1, args...);
    }
#else
#define trace(...) 0
#pragma GCC optimize ("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx2,sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define _CRT_SECURE_NO_WARNINGS
#endif // ifndef ONLINE_JUDGE

clock_t time_p=clock();
void TTIIMMEE()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}

const int RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash {
    int operator()(int x) const { return x ^ RANDOM; }
}; // datatype ki jagah gp_hash_table<key_type,int,chash> , for eg : Dp like hashmap : vector<gp_hash_table<int,int,chash>>dp(N);

//======================================================================================//
#define MOD 1000000007
int mod=1000000007;
#define int long long int
#define N 200005
int ar[N];
int n,a,b,c,d,m,k,q,t,x;
vec(int) v;

ll modexp(ll x, ll n,ll mod){ if(n==0)return 1; else if(n&1){return (modexp((x*x)%mod, n/2,mod)%mod * x%mod)%mod;}else{return (modexp((x*x)%mod, n/2,mod)%mod);}}
int modInverse(int n, int p) { return modexp(n, p-2, p); }
inline int add(int x,int y) {  return (x%mod + y%mod + mod)%mod; }
inline int mul(int x,int y) {  return (x%mod * y%mod + mod)%mod; }
inline int sub(int x,int y) {  return (x%mod - y%mod + mod)%mod; }

void bfs(int start,list<pii>adj[],set<pii>ans)
{
    queue<int>q;
    int visited[N];

    set<pii>done;
    q.push(start);
    visited[start]=1;

    while(!q.empty())
    {
        int node = q.front();
        q.pop();

        //cout<<"aaya "<<node<<endl;

        for(auto it:adj[node])
        {
            if(visited[it.F]==0)
            {
                q.push(it.F);
                visited[it.F]=1;
            }

            if(it.S==0 && done.find({it.F,node})==done.end())
            {
                ans.insert({it.F,node});
                it.S = -1;
                done.insert({node,it.F});
            }
        }
    }

    for(auto it:ans)
    {
        cout<<it.F<<" "<<it.S<<endl;
    }

}

int32_t main()
{
    fast();

    int testcase=1;    //change t if required
    cin>>testcase;
    while(testcase--)
    {
        set<pii>ans;
        cin>>n>>m;
        int out[n+1];
        mem(out,0);
        list<pii>adj[n+1];

        rep(i,m)
        {
            cin>>a>>b>>c;

            if(a==1){
                ans.insert({b,c});

                adj[b].pb({c,1});
                adj[c].pb({b,-1});
                out[b]++;
            }
            else
            {
                adj[b].pb({c,0});
                adj[c].pb({b,0});
            }
        }

        int start = 0;
        rep(i,n)
        {
            if(out[i+1]==0) start = i+1;
        }

        if(start==0)
        {
            cout<<"NO"<<endl;
        }
        else
        {
            cout<<"YES"<<endl;
            queue<int>q;
    int visited[N];

    set<pii>done;
    q.push(start);
    visited[start]=1;

    while(!q.empty())
    {
        int node = q.front();
        q.pop();

        //cout<<"aaya "<<node<<endl;

        for(auto it:adj[node])
        {
            if(visited[it.F]==0)
            {
                q.push(it.F);
                visited[it.F]=1;
            }

            if(it.S==0 && done.find({it.F,node})==done.end())
            {
                ans.insert({it.F,node});
                it.S = -1;
                done.insert({node,it.F});
            }
        }
    }

    for(auto it:ans)
    {
        cout<<it.F<<" "<<it.S<<endl;
    }
        }

    }
    TTIIMMEE();
    return 0;
}

void fast()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}


#include <bits/stdc++.h>
using namespace std;
bool cycle(int i,vector<vector<int>> &v,vector<int> &visited)
{
    visited[i]=1;
    for(auto &it:v[i])
    {
        if(visited[it]==1)
        return true;
        if(!visited[it] && cycle(it,v,visited))
        return true;
    }
    visited[i]=2;
    return false;
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    int t;
    cin>>t;
    while(t--)
    {
        int n,m;
        cin>>n>>m;
        vector<vector<int>> v(n+1);
        vector<int> indeg(n+1,0);
        vector<pair<int,int>> w,a;
        for(int i=0;i<m;i++)
        {
            int f,x,y;
            cin>>f>>x>>y;
            if(f==0)
            {
                w.push_back({x,y});
            }
            else
            {
                v[x].push_back(y);
                indeg[y]++;
                a.push_back({x,y});
            }
        }
        int f=0;
        vector<int> visited(n+1,0);
        for(int i=1;i<=n;i++)
        {
            if(visited[i])
            continue;
            if(cycle(i,v,visited))
            {
                f=1;
                break;
            }
        }
        if(f)
        {
            cout<<"NO\n";
            continue;
        }
        queue<int> q;
        vector<int> ans;
        for(int i=1;i<=n;i++)
        {
            if(indeg[i]==0)
            {
                q.push(i);
                ans.push_back(i);
            }
        }
        while(!q.empty())
        {
            int f=q.front();
            q.pop();
            for(auto &it:v[f])
            {
                indeg[it]--;
                if(indeg[it]==0)
                {
                    ans.push_back(it);
                    q.push(it);
                }
            }
        }
        unordered_map<int,int> mp;
        for(int i=0;i<ans.size();i++)
        {
            mp[ans[i]]=i;
        }
        cout<<"YES\n";
        for(int i=0;i<w.size();i++)
        {
            if(mp[w[i].first]<mp[w[i].second])
            cout<<w[i].first<<" "<<w[i].second<<"\n";
            else cout<<w[i].second<<" "<<w[i].first<<"\n";
        }
        for(int i=0;i<a.size();i++)
        {
            cout<<a[i].first<<" "<<a[i].second<<"\n";
        }
    }
	return 0;
}


// Khud ke baski to hai nai
    // isliye yaha dekhne aa gaye

//https://github.com/rafi-kamal/ACM-Solutions/blob/master/LightOj/String/1255%20-%20Substring%20Frequency.cpp

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;
void fast();
#define print(a)        for (auto x : a) cout << x << " "; cout << endl
#define print_upto(a,n)        for(int i=0;i<n;i++)    cout<<a[i]<<" "; cout<<endl
#define take(x,n)           for(int i=0;i<n;i++)  cin>>x[i];
#define rep(i,n)        for(int i=0;i<n;i++)
#define repange(i,a,b)      for(int i=a;i<=b;i++)
#define reprange(i,a,b)     for(int i=a;i>=b;i--)
#define okay    cout << "okay" << endl
#define hey     cout << "hey" << endl
#define ll long long
#define ull unsigned long long
#define ldob long double
#define dob double
#define F first
#define S second
#define pii pair<int, int>
#define vec(a) vector<a>
#define umap(a, b) unordered_map<a, b>
#define endl "\n"
#define inf 1e18
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define mem(a,b) memset(a,b,sizeof(a))

//======================================================================================//

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;  // ordered_set   cout << *(o_set.find_by_order(1))  and cout << o_set.order_of_key(4)
template <class T> ostream& operator << (ostream &os, const vector<T> &v) { for (T i : v) os << i << ", "; return os; }
template <class T> ostream& operator << (ostream &os, const set<T> &v) { for (T i : v) os << i << " "; return os; }
template <class T> ostream& operator << (ostream &os, const multiset<T> &v) { for (T i : v) os << i << " "; return os; }
template <class T, class S> ostream& operator << (ostream &os, const pair<T, S> &v) { os << v.F << ' ' << v.S; return os; }
template <class T, class S> ostream& operator << (ostream &os, const map<T, S> &v) { for (auto i : v) os << '(' << i.F << " => " << i.S << ')' << ' '; return os; }

typedef tree<int,null_type,less<int>,rb_tree_tag,tree_order_statistics_node_update>ordered_set;

#ifndef ONLINE_JUDGE
#define trace(...) _f(#VA_ARGS, __VA_ARGS_)
    template <class Arg1> void __f(const char* name, Arg1&& arg1) { cerr << name << " : " << arg1 << endl; }
    template <class Arg1, class... Args>
    void __f(const char* names, Arg1&& arg1, Args&&... args) {
        const char* sep = strchr(names + 1, ',');
        cerr.write(names, sep - names) << " : " << arg1 << "  ";
        __f(sep + 1, args...);
    }
#else
#define trace(...) 0
#pragma GCC optimize ("O3")
#pragma GCC optimize ("unroll-loops")
#pragma GCC target("avx2,sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define _CRT_SECURE_NO_WARNINGS
#endif // ifndef ONLINE_JUDGE

clock_t time_p=clock();
void TTIIMMEE()
{
    time_p=clock()-time_p;
    cerr<<"Time Taken : "<<(float)(time_p)/CLOCKS_PER_SEC<<"\n";
}

const int RANDOM = chrono::high_resolution_clock::now().time_since_epoch().count();
struct chash {
    int operator()(int x) const { return x ^ RANDOM; }
}; // datatype ki jagah gp_hash_table<key_type,int,chash> , for eg : Dp like hashmap : vector<gp_hash_table<int,int,chash>>dp(N);

//======================================================================================//
#define MOD 1000000007
int mod=1000000007;
#define int long long int
#define N 200005
int ar[N];
int n,a,b,c,d,m,k,q,t,x;
vec(int) v;

ll modexp(ll x, ll n,ll mod){ if(n==0)return 1; else if(n&1){return (modexp((x*x)%mod, n/2,mod)%mod * x%mod)%mod;}else{return (modexp((x*x)%mod, n/2,mod)%mod);}}
int modInverse(int n, int p) { return modexp(n, p-2, p); }
inline int add(int x,int y) {  return (x%mod + y%mod + mod)%mod; }
inline int mul(int x,int y) {  return (x%mod * y%mod + mod)%mod; }
inline int sub(int x,int y) {  return (x%mod - y%mod + mod)%mod; }

// void bfs(int start,list<pii>adj[],set<pii>ans)
// {
//     queue<int>q;
//     int visited[N];

//     set<pii>done;
//     q.push(start);
//     visited[start]=1;

//     while(!q.empty())
//     {
//         int node = q.front();
//         q.pop();

//         //cout<<"aaya "<<node<<endl;

//         for(auto it:adj[node])
//         {
//             if(visited[it.F]==0)
//             {
//                 q.push(it.F);
//                 visited[it.F]=1;
//             }

//             if(it.S==0 && done.find({it.F,node})==done.end())
//             {
//                 ans.insert({it.F,node});
//                 it.S = -1;
//                 done.insert({node,it.F});
//             }
//         }
//     }

//     for(auto it:ans)
//     {
//         cout<<it.F<<" "<<it.S<<endl;
//     }

// }

int32_t main()
{
    fast();

    int testcase=1;    //change t if required
    cin>>testcase;
    while(testcase--)
    {
        set<pii>ans;
        cin>>n>>m;
        int out[N];
        mem(out,0);
        list<pii>adj[N];

        rep(i,m)
        {
            cin>>a>>b>>c;

            if(a==1){
                ans.insert({b,c});

                adj[b].pb({c,1});
                adj[c].pb({b,-1});
                out[b]++;
            }
            else
            {
                adj[b].pb({c,0});
                adj[c].pb({b,0});
            }
        }

        int start = 0;
        rep(i,n)
        {
            if(out[i+1]==0) start = i+1;
        }

        if(start==0)
        {
            cout<<"NO"<<endl;
        }
        else
        {
            cout<<"YES"<<endl;

            ///BFS

            queue<int>q;
            int visited[N];

            set<pii>done;
            q.push(start);
            visited[start]=1;

            while(!q.empty())
            {
                int node = q.front();
                q.pop();

                //cout<<"aaya "<<node<<endl;

                for(auto it:adj[node])
                {
                    if(visited[it.F]==0)
                    {
                        q.push(it.F);
                        visited[it.F]=1;
                    }

                    if(it.S==0 && done.find({it.F,node})==done.end())
                    {
                        ans.insert({it.F,node});
                        it.S = -1;
                        done.insert({node,it.F});
                    }
                }
            }

            for(auto it:ans)
            {
                cout<<it.F<<" "<<it.S<<endl;
            }
        }

    }
    TTIIMMEE();
    return 0;
}

void fast()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL);
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
#ifndef ONLINE_JUDGE
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ll long long int
#define mp make_pair
#define S second
#define F first
ll mod=998244353 ;
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define input_from_file  freopen("input.txt", "r", stdin);
using namespace std::chrono;
ll n,m;
vector<vector<pair<ll,ll>>> vec,A;vector<bool> vis,vis2;
bool flag=0;
void cycle(ll i,vector<bool> &st) {
  vis2[i]=1;
  st[i]=1;
  for(auto x:A[i]){
    if(!vis2[x.S])  cycle(x.S,st);
    else if(st[x.S]==1) {flag=1;}
  }
  st[i]=0;
}
void dfs(ll i,ll par) {
  if(vis[i])  return;
  vis[i]=1;
  for(auto x:vec[i]){
    // cout<<"i="<<i<<" : ";
    // if(!vis[x.S]){
      if(par==x.S)  continue;
      cout<<i<<" "<<x.S<<endl;
      // else  cout<<x.S<<" "<<i<<endl;
      dfs(x.S,i);
    // }
  }
}
int main()
 {
  // input_from_file
  ll q;cin>>q;while(q--){
    flag=0;
    cin>>n>>m;
    vec.clear();vec.resize(n+1);A.clear();A.resize(n+1);
    vis.clear();vis.resize(n+1,0);vis2.clear();vis2.resize(n+1,0);
    for(int i=0;i<m;i++)  {ll t,u,v;
      cin>>t>>u>>v;
      // cout<<t<<" "<<u<<" "<<v<<" \n";
      if(t) {A[u].pb({t,v});vec[u].pb({t,v});}
      else  {vec[u].pb({t,v});vec[v].pb({t,u});}
    }
    vector<bool> st(n+1,0);
    for(int i=1;i<=n;i++){
      if(flag==0 && !vis2[i])
        cycle(i,st);
      if(flag)  break;
    }
    if(flag)  {cout<<"NO\n";continue;}
    cout<<"Yes\n";

    for(int i=1;i<=n;i++){
      if(!vis[i]) dfs(i,-1);
    }
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ll long long int
#define mp make_pair
#define S second
#define F first
ll mod=998244353 ;
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define input_from_file  freopen("input.txt", "r", stdin);
using namespace std::chrono;
ll n,m;
vector<vector<ll>> vec;
vector<pair<ll,ll>>A;vector<ll> order;
map<ll,ll> topo_order;
vector<bool> vis;
bool flag=0;
ll ctr=0;
void toposort(){
  ctr=0;
  topo_order.clear();
  order.resize(n+1,0);
  for(int i=1;i<=n;i++)   {
    for(auto x:vec[i])  order[x]++;
  }
  queue<ll> q;
  for(int i=1;i<=n;i++){
    if(order[i]==0) q.push(i);
  }
  while(!q.empty()){
    ll x=q.front();q.pop();
    for(auto y:vec[x]) {
      order[y]--;
      if(order[y]==0) q.push(y);
    }
    topo_order[x]=ctr++;
  }
}
int main()
 {
  // input_from_file
  ll q;cin>>q;while(q--){

    flag=0;
    cin>>n>>m;
    vec.resize(n+1);A.clear();
    vis.resize(n+1,0);
    for(int i=0;i<m;i++){ ll t,u,v;
      cin>>t>>u>>v;
      A.pb({u,v});  if(t) vec[u].pb(v);
    }
    toposort();
    if(ctr<n) {cout<<"NO\n";return 0;}
    cout<<"YES\n";
    for(int i=0;i<m;i++){
      ll x=A[i].F;    ll y=A[i].S;
      if(topo_order[x]>topo_order[y]) swap(x,y);
      cout<<x<<" "<<y<<endl;
    }
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ll long long int
#define mp make_pair
#define S second
#define F first
ll mod=998244353 ;
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define input_from_file  freopen("input.txt", "r", stdin);
using namespace std::chrono;
ll n,m;
vector<vector<pair<ll,ll>>> vec,A;vector<bool> vis,vis2;
bool flag=0;
void cycle(ll i,vector<bool> &st) {
  vis2[i]=1;
  st[i]=1;
  for(auto x:A[i]){
    if(!vis2[x.S])  cycle(x.S,st);
    else if(st[x.S]==1) {flag=1;}
  }
  st[i]=0;
}
void dfs(ll i,ll par) {
  if(vis[i])  return;
  vis[i]=1;
  for(auto x:vec[i]){
    if(x.S==par)  continue;
    // if(!vis[x.S]){
      if(x.F) cout<<i<<" "<<x.S<<endl;
      else  cout<<x.S<<" "<<i<<endl;
      dfs(x.S,i);
    // }
  }
}
int main()
 {
  // input_from_file
  ll q;cin>>q;while(q--){
    flag=0;
    cin>>n>>m;
    vec.clear();vec.resize(n+1);A.clear();A.resize(n+1);
    vis.clear();vis.resize(n+1,0);vis2.clear();vis2.resize(n+1,0);
    for(int i=0;i<m;i++)  {ll t,u,v;
      cin>>t>>u>>v;
      // cout<<t<<" "<<u<<" "<<v<<" \n";
      if(t) {A[u].pb({t,v});vec[u].pb({t,v});}
      else  {vec[u].pb({t,v});vec[v].pb({t,u});}
    }
    vector<bool> st(n+1,0);
    for(int i=1;i<=n;i++){
      if(flag==0 && !vis2[i])
        cycle(i,st);
      if(flag)  break;
    }
    if(flag)  {cout<<"NO\n";continue;}
    cout<<"Yes\n";

    for(int i=1;i<=n;i++){
      if(!vis[i]) dfs(i,-1);
    }
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ll long long int
#define mp make_pair
#define S second
#define F first
ll mod=998244353 ;
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define input_from_file  freopen("input.txt", "r", stdin);
using namespace std::chrono;
ll n,m;
vector<vector<ll>> vec;
vector<pair<ll,ll>>A;vector<ll> order;
map<ll,ll> topo_order;
ll ctr=0;
void toposort(){
  ctr=0;
  topo_order.clear();
  order.resize(n+1,0);
  for(int i=1;i<=n;i++)   {
    for(auto x:vec[i])  order[x]++;
  }
  queue<ll> q;
  for(int i=1;i<=n;i++){
    if(order[i]==0) q.push(i);
  }
  while(!q.empty()){
    ll x=q.front();q.pop();
    for(auto y:vec[x]) {
      order[y]--;
      if(order[y]==0) q.push(y);
    }
    topo_order[x]=ctr++;
  }
}
int main()
 {
  // input_from_file
  ll q;cin>>q;while(q--){
    cin>>n>>m;
    vec.resize(n+1);A.clear();
    for(int i=0;i<m;i++){ ll t,u,v;
      cin>>t>>u>>v;
      A.pb({u,v});  if(t) vec[u].pb(v);
    }
    toposort();
    if(ctr<n) {cout<<"NO\n";continue;}
    cout<<"YES\n";
    for(int i=0;i<m;i++){
      ll x=A[i].F;    ll y=A[i].S;
      if(topo_order[x]>topo_order[y]) swap(x,y);
      cout<<x<<" "<<y<<endl;
    }
  }
  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ll long long int
#define mp make_pair
#define S second
#define F first
ll mod=998244353 ;
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define input_from_file  freopen("input.txt", "r", stdin);
using namespace std::chrono;
ll n,m;
vector<vector<pair<ll,ll>>> vec,A;vector<bool> vis,vis2;
bool flag=0;
void cycle(ll i,vector<bool> &st) {
  vis2[i]=1;
  st[i]=1;
  for(auto x:A[i]){
    if(!vis2[x.S])  cycle(x.S,st);
    else if(st[x.S]==1) {flag=1;}
  }
  st[i]=0;
}
void dfs(ll i,ll par,ll dir) {
  if(vis[i])  return;
  vis[i]=1;
  for(auto x:vec[i]){
    // cout<<"i="<<i<<" : ";
    // if(!vis[x.S]){
      if(par==x.S)  continue;
      else if(x.F)  {
        cout<<i<<" "<<x.S<<endl;
        dfs(x.S,i,0);
      }
      else  {
        if(dir==0)  {
          cout<<x.S<<" "<<i<<endl;
          dfs(x.S,i,1);
        }
        else{
          cout<<i<<" "<<x.S<<endl;
          dfs(x.S,i,0);
        }

      }
    // }
  }
}
int main()
 {
  // input_from_file
  ll q;cin>>q;while(q--){
    flag=0;
    cin>>n>>m;
    vec.clear();vec.resize(n+1);A.clear();A.resize(n+1);
    vis.clear();vis.resize(n+1,0);vis2.clear();vis2.resize(n+1,0);
    for(int i=0;i<m;i++)  {ll t,u,v;
      cin>>t>>u>>v;
      // cout<<t<<" "<<u<<" "<<v<<" \n";
      if(t) {A[u].pb({t,v});vec[u].pb({t,v});}
      else  {vec[u].pb({t,v});vec[v].pb({t,u});}
    }
    vector<bool> st(n+1,0);
    for(int i=1;i<=n;i++){
      if(flag==0 && !vis2[i])
        cycle(i,st);
      if(flag)  break;
    }
    if(flag)  {cout<<"NO\n";continue;}
    cout<<"Yes\n";

    for(int i=1;i<=n;i++){
      if(!vis[i]) dfs(i,-1,1);
    }
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ll long long int
#define mp make_pair
#define S second
#define F first
ll mod=998244353 ;
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define input_from_file  freopen("input.txt", "r", stdin);
using namespace std::chrono;
ll n,m;
vector<vector<pair<ll,ll>>> vec,A;vector<bool> vis,vis2;
bool flag=0;
void cycle(ll i,vector<bool> &st) {
  vis2[i]=1;
  st[i]=1;
  for(auto x:A[i]){
    if(!vis2[x.S])  cycle(x.S,st);
    else if(st[x.S]==1) {flag=1;}
  }
  st[i]=0;
}
void dfs(ll i,ll par,ll dir) {
  if(vis[i])  return;
  vis[i]=1;
  for(auto x:vec[i]){
    // cout<<"i="<<i<<" : ";
    // if(!vis[x.S]){
      if(par==x.S)  continue;
      else if(x.F)  {
        cout<<i<<" "<<x.S<<endl;
        dfs(x.S,i,0);
      }
      else  {
        if(dir==0)  {
          cout<<x.S<<" "<<i<<endl;
          dfs(x.S,i,1);
        }
        else{
          cout<<i<<" "<<x.S<<endl;
          dfs(x.S,i,0);
        }

      }
    // }
  }
}
int main()
 {
  // input_from_file
  ll q;cin>>q;while(q--){
    flag=0;
    cin>>n>>m;
    vec.clear();vec.resize(n+1);A.clear();A.resize(n+1);
    vis.clear();vis.resize(n+1,0);vis2.clear();vis2.resize(n+1,0);
    for(int i=0;i<m;i++)  {ll t,u,v;
      cin>>t>>u>>v;
      // cout<<t<<" "<<u<<" "<<v<<" \n";
      if(t) {A[u].pb({t,v});vec[u].pb({t,v});}
      else  {vec[u].pb({t,v});vec[v].pb({t,u});}
    }
    vector<bool> st(n+1,0);
    for(int i=1;i<=n;i++){
      if(flag==0 && !vis2[i])
        cycle(i,st);
      if(flag)  break;
    }
    if(flag)  {cout<<"NO\n";continue;}
    cout<<"Yes\n";

    for(int i=1;i<=n;i++){
      if(!vis[i]) dfs(i,-1,0);
    }
  }

  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define ll long long int
#define mp make_pair
#define S second
#define F first
ll mod=998244353 ;
#define fastIO ios_base::sync_with_stdio(false); cin.tie(NULL);
#define input_from_file  freopen("input.txt", "r", stdin);
using namespace std::chrono;

int main()
 {
  // input_from_file
  ll q;cin>>q;while(q--){
    ll n,m;
    cin>>n>>m;
    vector<vector<ll>> vec(n+1);
    vector<pair<ll,ll>>A;vector<ll> order(n+1,0);
    for(int i=0;i<m;i++){ ll t,u,v;
      cin>>t>>u>>v;
      A.pb({u,v});  if(t) vec[u].pb(v);
    }
    map<ll,ll> topo_order;
    ll ctr=0;
    for(int i=1;i<=n;i++)   {
      for(auto x:vec[i])  order[x]++;
    }
    queue<ll> q;
    for(int i=1;i<=n;i++){
      if(order[i]==0) q.push(i);
    }
    while(!q.empty()){
      ll x=q.front();q.pop();
      for(auto y:vec[x]) {
        order[y]--;
        if(order[y]==0) q.push(y);
      }
      topo_order[x]=ctr++;
    }

    if(ctr<n) {cout<<"NO\n";continue;}
    cout<<"YES\n";
    for(int i=0;i<m;i++){
      ll x=A[i].F;    ll y=A[i].S;
      if(topo_order[x]>topo_order[y]) swap(x,y);
      cout<<x<<" "<<y<<endl;
    }
  }
  return 0;
}


#include<iostream>
#include<list>
#include<string>
#include<cstring>
#include<sstream>
#include<cctype>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<utility>
#include<iomanip>
#include<queue>
using namespace std;

#define LL long long int
#define uLL unsigned long long int

#define S(a) scanf("%d",&a)
#define S2(a,b) scanf("%d%d",&a,&b)
#define S3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define SLL(a) scanf("%lld",&a)
#define SLL2(a,b) scanf("%lld%lld",&a,&b)
#define SLL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define SC(a) scanf("%c",&a)
#define P(a) printf("%d",a)
#define PS(a) printf("%s",a)
#define PLL(a) printf("%lld",a)
#define PCASE(kk) printf("Case %d: ",kk++)
#define PCASENL(kk) printf("Case %d:\n",kk++)
#define NL puts("")

#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define pi (2.0*acos(0.0))
#define pii pair<int,int>

template<typename T>inline T POW(T B,T P)
{
    if(P==0) return 1;
    if(P&1) return B*POW(B,P-1);
    else return SQR(POW(B,P/2));
}
template <class T> inline T BMOD(T p,T e,T m)
{
    T ret=1;
    while(e)
    {
        if(e&1) ret=(ret*p)%m;
        p=(p*p)%m;
        e>>=1;
    }
    return (T)ret;
}
template <typename T>inline T ModInv (T b,T m)
{
    return BMOD(b,m-2,m);
}
template<typename T>inline T ABS(T a)
{
    if(a<0)return -a;
    else return a;
}
template<typename T>inline T gcd(T a,T b)
{
    if(a<0)return gcd(-a,b);
    if(b<0)return gcd(a,-b);
    return (b==0)?a:gcd(b,a%b);
}
template<typename T>inline T lcm(T a,T b)
{
    if(a<0)return lcm(-a,b);
    if(b<0)return lcm(a,-b);
    return a*(b/gcd(a,b));
}

//for(__typeof(pp.begin()) i=pp.begin(); i!=pp.end(); i++ )

//knight and king move....

//int Dx[]={-2,-1,1,2,1,2,-2,-1};
//int Dy[]={-1,-2,2,1,-2,-1,1,2};
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
//int dx[]= {-1,-1,0,0,1,1};
//int dy[]= {-1,0,-1,1,0,1};
/////////////

vector<pair<int, int> > edges;
vector<int> gp[200005], tpos;
int n,m;
int vis[200005];
bool cycle;

void findCycle(int u) {
    vis[u]=1;
    for(int v: gp[u]) {
        if(vis[v] == 1) {
            cycle = true;
            return ;
        } else if(vis[v] == 0) {
            findCycle(v);
        }
    }
    vis[u]=2;
}

void topsort(int u) {

    vis[u]=1;
    for(int v: gp[u]) {
        if(vis[v]==0)topsort(v);
    }
    tpos.pb(u);
}

int main() {
    int t,tc=1;
    S(t);
    while(t--) {

        S2(n,m);

        for(int i=0;i<=n;i++) {
            gp[i].clear();
        }
        edges.clear();

        for(int i=1;i<=m;i++) {
            int ty,u,v;
            S3(ty, u, v);
            edges.pb(mp(u,v));
            if(ty==1) {
                gp[u].pb(v);
            }
        }

        tpos.clear();
        memset(vis, 0, sizeof vis);

        cycle = false;
        for(int i=1;i<=n;i++) {
            if(vis[i]==0) {
                findCycle(i);
            }

            if(cycle)break;
        }

        if(cycle) {
            printf("NO\n");
        } else {
            memset(vis, 0, sizeof vis);
            for(int i=1;i<=n;i++) {
                if(vis[i]==0) {
                    topsort(i);
                }
            }
            reverse(tpos.begin(), tpos.end());

            for(int i=0;i<tpos.size();i++) {
                vis[tpos[i]] = i;
                //cout<<tpos[i]<<""
            }
            printf("YES\n");
            for(int i=0;i<m;i++) {
                int u = edges[i].first;
                int v = edges[i].second;

                if(vis[u] < vis[v]) {
                    printf("%d %d\n", u, v);
                } else {
                    printf("%d %d\n", v, u);
                }
            }
        }

    }
    return 0;
}


#include<iostream>
#include<list>
#include<string>
#include<cstring>
#include<sstream>
#include<cctype>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<utility>
#include<iomanip>
#include<queue>
using namespace std;

#define LL long long int
#define uLL unsigned long long int

#define S(a) scanf("%d",&a)
#define S2(a,b) scanf("%d%d",&a,&b)
#define S3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define SLL(a) scanf("%lld",&a)
#define SLL2(a,b) scanf("%lld%lld",&a,&b)
#define SLL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define SC(a) scanf("%c",&a)
#define P(a) printf("%d",a)
#define PS(a) printf("%s",a)
#define PLL(a) printf("%lld",a)
#define PCASE(kk) printf("Case %d: ",kk++)
#define PCASENL(kk) printf("Case %d:\n",kk++)
#define NL puts("")

#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define pi (2.0*acos(0.0))
#define pii pair<int,int>

template<typename T>inline T POW(T B,T P)
{
    if(P==0) return 1;
    if(P&1) return B*POW(B,P-1);
    else return SQR(POW(B,P/2));
}
template <class T> inline T BMOD(T p,T e,T m)
{
    T ret=1;
    while(e)
    {
        if(e&1) ret=(ret*p)%m;
        p=(p*p)%m;
        e>>=1;
    }
    return (T)ret;
}
template <typename T>inline T ModInv (T b,T m)
{
    return BMOD(b,m-2,m);
}
template<typename T>inline T ABS(T a)
{
    if(a<0)return -a;
    else return a;
}
template<typename T>inline T gcd(T a,T b)
{
    if(a<0)return gcd(-a,b);
    if(b<0)return gcd(a,-b);
    return (b==0)?a:gcd(b,a%b);
}
template<typename T>inline T lcm(T a,T b)
{
    if(a<0)return lcm(-a,b);
    if(b<0)return lcm(a,-b);
    return a*(b/gcd(a,b));
}

//for(__typeof(pp.begin()) i=pp.begin(); i!=pp.end(); i++ )

//knight and king move....

//int Dx[]={-2,-1,1,2,1,2,-2,-1};
//int Dy[]={-1,-2,2,1,-2,-1,1,2};
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
//int dx[]= {-1,-1,0,0,1,1};
//int dy[]= {-1,0,-1,1,0,1};
/////////////

vector<pair<int, int> > edges;
vector<int> gp[200005], tpos;
int n,m;
int vis[200005];
bool cycle;

void topsort(int u) {

    vis[u]=1;
    for(int v: gp[u]) {
        if(vis[v] == 1) {
            cycle = true;
            return ;
        } else {
            topsort(v);
        }
    }
    vis[u]=2;
    tpos.pb(u);
}

int main() {
    int t,tc=1;
    S(t);
    while(t--) {

        S2(n,m);

        for(int i=0;i<=n;i++) {
            gp[i].clear();
        }
        edges.clear();

        for(int i=1;i<=m;i++) {
            int ty,u,v;
            S3(ty, u, v);
            edges.pb(mp(u,v));
            if(ty==1) {
                gp[u].pb(v);
            }
        }

        tpos.clear();
        cycle = false;
        for(int i=1;i<=n;i++) {
            if(vis[i]==0) {
                topsort(i);
            }

            if(cycle)break;
        }

        if(cycle) {
            printf("NO\n");
        } else {
            reverse(tpos.begin(), tpos.end());
            memset(vis, 0, sizeof vis);

            for(int i=0;i<tpos.size();i++) {
                vis[tpos[i]] = i;
            }
            printf("YES\n");
            for(int i=0;i<m;i++) {
                int u = edges[i].first;
                int v = edges[i].second;

                if(vis[u] < vis[v]) {
                    printf("%d %d\n", u, v);
                } else {
                    printf("%d %d\n", v, u);
                }
            }
        }

    }
    return 0;
}


#include<iostream>
#include<list>
#include<string>
#include<cstring>
#include<sstream>
#include<cctype>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<utility>
#include<iomanip>
#include<queue>
using namespace std;

#define LL long long int
#define uLL unsigned long long int

#define S(a) scanf("%d",&a)
#define S2(a,b) scanf("%d%d",&a,&b)
#define S3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define SLL(a) scanf("%lld",&a)
#define SLL2(a,b) scanf("%lld%lld",&a,&b)
#define SLL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define SC(a) scanf("%c",&a)
#define P(a) printf("%d",a)
#define PS(a) printf("%s",a)
#define PLL(a) printf("%lld",a)
#define PCASE(kk) printf("Case %d: ",kk++)
#define PCASENL(kk) printf("Case %d:\n",kk++)
#define NL puts("")

#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define pi (2.0*acos(0.0))
#define pii pair<int,int>

template<typename T>inline T POW(T B,T P)
{
    if(P==0) return 1;
    if(P&1) return B*POW(B,P-1);
    else return SQR(POW(B,P/2));
}
template <class T> inline T BMOD(T p,T e,T m)
{
    T ret=1;
    while(e)
    {
        if(e&1) ret=(ret*p)%m;
        p=(p*p)%m;
        e>>=1;
    }
    return (T)ret;
}
template <typename T>inline T ModInv (T b,T m)
{
    return BMOD(b,m-2,m);
}
template<typename T>inline T ABS(T a)
{
    if(a<0)return -a;
    else return a;
}
template<typename T>inline T gcd(T a,T b)
{
    if(a<0)return gcd(-a,b);
    if(b<0)return gcd(a,-b);
    return (b==0)?a:gcd(b,a%b);
}
template<typename T>inline T lcm(T a,T b)
{
    if(a<0)return lcm(-a,b);
    if(b<0)return lcm(a,-b);
    return a*(b/gcd(a,b));
}

//for(__typeof(pp.begin()) i=pp.begin(); i!=pp.end(); i++ )

//knight and king move....

//int Dx[]={-2,-1,1,2,1,2,-2,-1};
//int Dy[]={-1,-2,2,1,-2,-1,1,2};
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
//int dx[]= {-1,-1,0,0,1,1};
//int dy[]= {-1,0,-1,1,0,1};
/////////////

vector<pair<int, int> > edges;
vector<int> gp[200005], tpos;
int n,m;
int vis[200005];
bool cycle;

void topsort(int u) {

    vis[u]=1;
    for(int v: gp[u]) {
        if(vis[v] == 1) {
            cycle = true;
            return ;
        } else {
            topsort(v);
        }
    }
    vis[u]=2;
    tpos.pb(u);
}

int main() {
    int t,tc=1;
    S(t);
    while(t--) {

        S2(n,m);

        for(int i=0;i<=n;i++) {
            gp[i].clear();
        }
        edges.clear();

        for(int i=1;i<=m;i++) {
            int ty,u,v;
            S3(ty, u, v);
            edges.pb(mp(u,v));
            if(ty==1) {
                gp[u].pb(v);
            }
        }

        tpos.clear();
        cycle = false;
        for(int i=1;i<=n;i++) {
            if(vis[i]==0) {
                topsort(i);
            }

            if(cycle)break;
        }

        if(cycle) {
            printf("No\n");
        } else {
            reverse(tpos.begin(), tpos.end());
            memset(vis, 0, sizeof vis);

            for(int i=0;i<n;i++) {
                vis[tpos[i]] = i;
            }
            printf("Yes\n");
            for(int i=0;i<m;i++) {
                int u = edges[i].first;
                int v = edges[i].second;

                if(vis[u] < vis[v]) {
                    printf("%d %d\n", u, v);
                } else {
                    printf("%d %d\n", v, u);
                }
            }
        }

    }
    return 0;
}


#include<iostream>
#include<list>
#include<string>
#include<cstring>
#include<sstream>
#include<cctype>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<utility>
#include<iomanip>
#include<queue>
using namespace std;

#define LL long long int
#define uLL unsigned long long int

#define S(a) scanf("%d",&a)
#define S2(a,b) scanf("%d%d",&a,&b)
#define S3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define SLL(a) scanf("%lld",&a)
#define SLL2(a,b) scanf("%lld%lld",&a,&b)
#define SLL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define SC(a) scanf("%c",&a)
#define P(a) printf("%d",a)
#define PS(a) printf("%s",a)
#define PLL(a) printf("%lld",a)
#define PCASE(kk) printf("Case %d: ",kk++)
#define PCASENL(kk) printf("Case %d:\n",kk++)
#define NL puts("")

#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define pi (2.0*acos(0.0))
#define pii pair<int,int>

template<typename T>inline T POW(T B,T P)
{
    if(P==0) return 1;
    if(P&1) return B*POW(B,P-1);
    else return SQR(POW(B,P/2));
}
template <class T> inline T BMOD(T p,T e,T m)
{
    T ret=1;
    while(e)
    {
        if(e&1) ret=(ret*p)%m;
        p=(p*p)%m;
        e>>=1;
    }
    return (T)ret;
}
template <typename T>inline T ModInv (T b,T m)
{
    return BMOD(b,m-2,m);
}
template<typename T>inline T ABS(T a)
{
    if(a<0)return -a;
    else return a;
}
template<typename T>inline T gcd(T a,T b)
{
    if(a<0)return gcd(-a,b);
    if(b<0)return gcd(a,-b);
    return (b==0)?a:gcd(b,a%b);
}
template<typename T>inline T lcm(T a,T b)
{
    if(a<0)return lcm(-a,b);
    if(b<0)return lcm(a,-b);
    return a*(b/gcd(a,b));
}

//for(__typeof(pp.begin()) i=pp.begin(); i!=pp.end(); i++ )

//knight and king move....

//int Dx[]={-2,-1,1,2,1,2,-2,-1};
//int Dy[]={-1,-2,2,1,-2,-1,1,2};
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
//int dx[]= {-1,-1,0,0,1,1};
//int dy[]= {-1,0,-1,1,0,1};
/////////////

vector<pair<int, int> > edges;
vector<int> gp[200005], tpos;
int n,m;
int vis[200005];
bool cycle;

void topsort(int u) {

    vis[u]=1;
    for(int v: gp[u]) {
        if(vis[v] == 1) {
            cycle = true;
            return ;
        } else {
            topsort(v);
        }
    }
    vis[u]=2;
    tpos.pb(u);
}

int main() {
    int t,tc=1;
    S(t);
    while(t--) {

        S2(n,m);

        for(int i=0;i<=n;i++) {
            gp[i].clear();
        }
        edges.clear();

        for(int i=1;i<=m;i++) {
            int ty,u,v;
            S3(ty, u, v);
            edges.pb(mp(u,v));
            if(ty==1) {
                gp[u].pb(v);
            }
        }

        tpos.clear();
        cycle = false;
        for(int i=1;i<=n;i++) {
            if(vis[i]==0) {
                topsort(i);
            }

            if(cycle)break;
        }

        if(cycle) {
            printf("NO\n");
        } else {
            reverse(tpos.begin(), tpos.end());
            memset(vis, 0, sizeof vis);

            for(int i=0;i<n;i++) {
                vis[tpos[i]] = i;
            }
            printf("YES\n");
            for(int i=0;i<m;i++) {
                int u = edges[i].first;
                int v = edges[i].second;

                if(vis[u] < vis[v]) {
                    printf("%d %d\n", u, v);
                } else {
                    printf("%d %d\n", v, u);
                }
            }
        }

    }
    return 0;
}


#include<iostream>
#include<list>
#include<string>
#include<cstring>
#include<sstream>
#include<cctype>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<utility>
#include<iomanip>
#include<queue>
using namespace std;

#define LL long long int
#define uLL unsigned long long int

#define S(a) scanf("%d",&a)
#define S2(a,b) scanf("%d%d",&a,&b)
#define S3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define SLL(a) scanf("%lld",&a)
#define SLL2(a,b) scanf("%lld%lld",&a,&b)
#define SLL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define SC(a) scanf("%c",&a)
#define P(a) printf("%d",a)
#define PS(a) printf("%s",a)
#define PLL(a) printf("%lld",a)
#define PCASE(kk) printf("Case %d: ",kk++)
#define PCASENL(kk) printf("Case %d:\n",kk++)
#define NL puts("")

#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define pi (2.0*acos(0.0))
#define pii pair<int,int>

template<typename T>inline T POW(T B,T P)
{
    if(P==0) return 1;
    if(P&1) return B*POW(B,P-1);
    else return SQR(POW(B,P/2));
}
template <class T> inline T BMOD(T p,T e,T m)
{
    T ret=1;
    while(e)
    {
        if(e&1) ret=(ret*p)%m;
        p=(p*p)%m;
        e>>=1;
    }
    return (T)ret;
}
template <typename T>inline T ModInv (T b,T m)
{
    return BMOD(b,m-2,m);
}
template<typename T>inline T ABS(T a)
{
    if(a<0)return -a;
    else return a;
}
template<typename T>inline T gcd(T a,T b)
{
    if(a<0)return gcd(-a,b);
    if(b<0)return gcd(a,-b);
    return (b==0)?a:gcd(b,a%b);
}
template<typename T>inline T lcm(T a,T b)
{
    if(a<0)return lcm(-a,b);
    if(b<0)return lcm(a,-b);
    return a*(b/gcd(a,b));
}

//for(__typeof(pp.begin()) i=pp.begin(); i!=pp.end(); i++ )

//knight and king move....

//int Dx[]={-2,-1,1,2,1,2,-2,-1};
//int Dy[]={-1,-2,2,1,-2,-1,1,2};
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
//int dx[]= {-1,-1,0,0,1,1};
//int dy[]= {-1,0,-1,1,0,1};
/////////////

vector<pair<int, int> > edges;
vector<int> gp[200005], tpos;
int n,m,ftime;
int vis[200005];
bool cycle;

void topsort(int u) {

    vis[u]=1;
    for(int v: gp[u]) {
        if(vis[v] == 1) {
            cycle = true;
            return ;
        } else {
            topsort(v);
        }
    }
    vis[u]=2;
    tpos.pb(u);
}

int main() {
    int t,tc=1;
    S(t);
    while(t--) {

        S2(n,m);

        for(int i=0;i<=n;i++) {
            gp[i].clear();
        }
        edges.clear();

        for(int i=1;i<=m;i++) {
            int ty,u,v;
            S3(ty, u, v);
            edges.pb(mp(u,v));
            if(ty==1) {
                gp[u].pb(v);
            }
        }

        tpos.clear();
        cycle = false;
        for(int i=1;i<=n;i++) {
            if(vis[i]==0) {
                topsort(i);
            }

            if(cycle)break;
        }

        if(cycle) {
            printf("No\n");
        } else {
            reverse(tpos.begin(), tpos.end());
            memset(vis, 0, sizeof vis);

            for(int i=0;i<n;i++) {
                vis[tpos[i]] = i;
            }
            printf("Yes\n");
            for(int i=0;i<m;i++) {
                int u = edges[i].first;
                int v = edges[i].second;

                if(vis[u] < vis[v]) {
                    printf("%d %d\n", u, v);
                } else {
                    printf("%d %d\n", v, u);
                }
            }
        }

    }
    return 0;
}


#include<iostream>
#include<list>
#include<string>
#include<cstring>
#include<sstream>
#include<cctype>
#include<string.h>
#include<algorithm>
#include<cmath>
#include<stack>
#include<fstream>
#include<cstdlib>
#include<vector>
#include<map>
#include<set>
#include<utility>
#include<iomanip>
#include<queue>
using namespace std;

#define LL long long int
#define uLL unsigned long long int

#define S(a) scanf("%d",&a)
#define S2(a,b) scanf("%d%d",&a,&b)
#define S3(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define SLL(a) scanf("%lld",&a)
#define SLL2(a,b) scanf("%lld%lld",&a,&b)
#define SLL3(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define SC(a) scanf("%c",&a)
#define P(a) printf("%d",a)
#define PS(a) printf("%s",a)
#define PLL(a) printf("%lld",a)
#define PCASE(kk) printf("Case %d: ",kk++)
#define PCASENL(kk) printf("Case %d:\n",kk++)
#define NL puts("")

#define pb(a) push_back(a)
#define mp(a,b) make_pair(a,b)
#define pi (2.0*acos(0.0))
#define pii pair<int,int>

template<typename T>inline T POW(T B,T P)
{
    if(P==0) return 1;
    if(P&1) return B*POW(B,P-1);
    else return SQR(POW(B,P/2));
}
template <class T> inline T BMOD(T p,T e,T m)
{
    T ret=1;
    while(e)
    {
        if(e&1) ret=(ret*p)%m;
        p=(p*p)%m;
        e>>=1;
    }
    return (T)ret;
}
template <typename T>inline T ModInv (T b,T m)
{
    return BMOD(b,m-2,m);
}
template<typename T>inline T ABS(T a)
{
    if(a<0)return -a;
    else return a;
}
template<typename T>inline T gcd(T a,T b)
{
    if(a<0)return gcd(-a,b);
    if(b<0)return gcd(a,-b);
    return (b==0)?a:gcd(b,a%b);
}
template<typename T>inline T lcm(T a,T b)
{
    if(a<0)return lcm(-a,b);
    if(b<0)return lcm(a,-b);
    return a*(b/gcd(a,b));
}

//for(__typeof(pp.begin()) i=pp.begin(); i!=pp.end(); i++ )

//knight and king move....

//int Dx[]={-2,-1,1,2,1,2,-2,-1};
//int Dy[]={-1,-2,2,1,-2,-1,1,2};
int dx[]= {-1,1,0,0};
int dy[]= {0,0,-1,1};
//int dx[]= {-1,-1,0,0,1,1};
//int dy[]= {-1,0,-1,1,0,1};
/////////////

vector<pair<int, int> > edges;
vector<int> gp[200005], tpos;
int n,m;
int vis[200005];
bool cycle;

void topsort(int u) {

    vis[u]=1;
    for(int v: gp[u]) {
        if(vis[v] == 1) {
            cycle = true;
            return ;
        } else if(vis[v]==0) {
            topsort(v);
        }
    }
    vis[u]=2;
    tpos.pb(u);
}

int main() {
    int t,tc=1;
    S(t);
    while(t--) {

        S2(n,m);

        for(int i=0;i<=n;i++) {
            gp[i].clear();
        }
        edges.clear();

        for(int i=1;i<=m;i++) {
            int ty,u,v;
            S3(ty, u, v);
            edges.pb(mp(u,v));
            if(ty==1) {
                gp[u].pb(v);
            }
        }

        tpos.clear();
        cycle = false;
        for(int i=1;i<=n;i++) {
            if(vis[i]==0) {
                topsort(i);
            }

            if(cycle)break;
        }

        if(cycle) {
            printf("NO\n");
        } else {
            reverse(tpos.begin(), tpos.end());
            memset(vis, 0, sizeof vis);

            for(int i=0;i<tpos.size();i++) {
                vis[tpos[i]] = i;
            }
            printf("YES\n");
            for(int i=0;i<m;i++) {
                int u = edges[i].first;
                int v = edges[i].second;

                if(vis[u] < vis[v]) {
                    printf("%d %d\n", u, v);
                } else {
                    printf("%d %d\n", v, u);
                }
            }
        }

    }
    return 0;
}