////#define DEBUG
#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;

#define BSET(a, p) ((a) | (1ll << (p)))
#define BCHK(a, p) ((a) & (1ll << (p)))
#define BXOR(a, p) ((a) ^ (1ll << (p)));
#define BREM(a, p) (BCHK(a, p)?(BXOR(a, p)):(a))
#define BSHO(a, N) (bitset<N>(a))

#define fi first
#define sc second 
#define pb push_back


#ifdef DEBUG
    #define dbg(s) {s;}
    #define PRELUDE
#endif

#ifndef DEBUG 
    #define PRELUDE { ios :: sync_with_stdio(false); cin.tie(0); cout.tie(0); }
    #define dbg(s)
    #define endl "\n"
#endif

using namespace std;


#define int ll
#define i32 int32_t

#define RBTTYPE int
#define ordered_set tree<RBTTYPE, null_type, less<RBTTYPE>, rb_tree_tag,tree_order_statistics_node_update> 

#define all(v) (v).begin(),(v).end()

typedef long long ll;
typedef long double ld;
typedef pair< int, int > pii;
typedef pair< ll, ll > pll;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
inline int ri(int x) { // from [0, n-1]
    return uniform_int_distribution<int>(0, x - 1)(rng);
}

inline ld rf() { // from [0, 1]
    return uniform_real_distribution<ld>(0, 1)(rng);
}

ll gcd(ll x, ll y) {
    if (x < y) return gcd(y, x);
    if (y == 0) return x;
    return gcd(y, x % y);
} 

const ll mod = 1e9 + 7;

ll modexp(ll x, ll ex) {
    ll ans = 1ll;
    while (ex > 0) {
        if (ex & 1ll) ans = (ans * x) % mod;
        ex >>= 1ll;
        x = (x * x) % mod;
    }
    return ans;
}

const int maxn = 1e6 + 7;

const ll inf = 1e9 + 7;


int dsu[maxn];
void _union(int x, int y) {
    dsu[x] = y;
}
int _find(int x) {
    if (dsu[x] < 0) return x;
    return (dsu[x] = _find(dsu[x]));
}

vector < pii > t2;


i32 main() {
    //freopen("<file>.in", "r", stdin);
    //freopen("<file>.out", "w", stdout);
    
    PRELUDE;
    
    int n, m, q; cin >> n >> m >> q;

    fill(dsu, dsu + maxn, -1);

    for (int j = 1; j <= q; j++) {
        int x, y, t; cin >> x >> y >> t; x++; y++;
        if (t == 0) {
            int a = _find(x), b = _find(y);
            if (a == b) continue;
            _union(a, b);
        } else {
            t2.pb({x, y});
        }
    }

    int idx = 0;
    
    static int par[maxn];
    static int szpar[maxn];
    static vector < int > tops;

    fill(szpar, szpar + maxn, 0);
    int edins = 0;

    for (int j = 1; j <= n; j++) {
        par[j] = _find(j);
        dbg(cout << j << " : " << par[j] <<endl;);
        szpar[par[j]]++;
        if (szpar[par[j]] > 1) edins++;
        tops.pb(par[j]);
    }

    sort(all(tops)); tops.resize(unique(all(tops)) - tops.begin());
    
    int comp = tops.size();
    int mx = comp * (comp - 1) / 2 + edins; 

    fill(dsu, dsu + maxn, -1);

    for (auto z : t2) {
        int x = z.fi, y = z.sc;
        int a = par[x], b = par[y];
        if (a == b) {
            cout << "No" << endl; return 0;
        }
        a = _find(a); b = _find(b);
        if (a == b) continue;
        _union(a, b);
    }

    static int sz[maxn];
    fill(sz, sz + maxn, 0);
    for (int v : tops) {
        sz[_find(v)]++;
    }

    int mn = edins;

    for (int j = 0; j < maxn; j++) {
        mn += (sz[j] > 1) ? sz[j] : 0;
    }

    cout << ((mn <= m && m <= mx) ? "Yes" : "No") << endl;
}




Measured memory_bytes: 30832