Problem:
Score : 700 points

Problem Statement

Snuke's mother gave Snuke an undirected graph consisting of N vertices numbered 0 to N-1 and M edges.
This graph was connected and contained no parallel edges or self-loops.

One day, Snuke broke this graph.
Fortunately, he remembered Q clues about the graph.
The i-th clue (0 \leq i \leq Q-1) is represented as integers A_i,B_i,C_i and means the following:

If C_i=0: there was exactly one simple path (a path that never visits the same vertex twice) from Vertex A_i to B_i.

If C_i=1: there were two or more simple paths from Vertex A_i to B_i.

Snuke is not sure if his memory is correct, and worried whether there is a graph that matches these Q clues.
Determine if there exists a graph that matches Snuke's memory.

Constraints

2 \leq N \leq 10^5

N-1 \leq M \leq N \times (N-1)/2

1 \leq Q \leq 10^5

0 \leq A_i,B_i \leq N-1

A_i \neq B_i

0 \leq C_i \leq 1

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M Q
A_0 B_0 C_0
A_1 B_1 C_1
\vdots
A_{Q-1} B_{Q-1} C_{Q-1}

Output

If there exists a graph that matches Snuke's memory, print Yes; otherwise, print No.

Sample Input 1

5 5 3
0 1 0
1 2 1
2 3 0

Sample Output 1

Yes

For example, consider a graph with edges (0,1),(1,2),(1,4),(2,3),(2,4). This graph matches the clues.

Sample Input 2

4 4 3
0 1 0
1 2 1
2 3 0

Sample Output 2

No

Sample Input 3

10 9 9
7 6 0
4 5 1
9 7 0
2 9 0
2 3 0
4 1 0
8 0 0
9 1 0
3 0 0

Sample Output 3

No

Solution in C++14 (GCC 5.4.1) (judge verdict: Runtime Error)

#include "bits/stdc++.h"

#define REP(i, n) for (ll i = 0; i < ll(n); ++i)
#define RREP(i, n) for (ll i = ll(n) - 1; i >= 0; --i)
#define FOR(i, m, n) for (ll i = m; i < ll(n); ++i)
#define RFOR(i, m, n) for (ll i = ll(n) - 1; i >= ll(m); --i)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) v.erase(unique(ALL(v)), v.end());
#define INF 1000000001ll
#define MOD 1000000007ll
#define EPS 1e-9

constexpr int dx[8] = {1, 1, 0, -1, -1, -1, 0, 1};
constexpr int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};

using namespace std;

using ll = long long;
using vi = vector<int>;
using vl = vector<ll>;
using vvi = vector<vi>;
using vvl = vector<vl>;
using pii = pair<int, int>;
using pll = pair<ll, ll>;

template <class T> bool chmin(T &a, const T &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}
template <class T> bool chmax(T &a, const T &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}
#include "bits/stdc++.h"
struct UnionFind {
  std::vector<int> par;
  std::vector<int> sizes;

  UnionFind(int n) {
    par.resize(n);
    sizes.resize(n);
    for (int i = 0; i < n; ++i) {
      par[i] = i;
      sizes[i] = 1;
    }
  }

  int root(int a) { return par[a] == a ? a : par[a] = root(par[a]); }

  bool same(int x, int y) { return root(x) == root(y); }

  void unite(int x, int y) {
    x = root(x);
    y = root(y);
    if (x == y)
      return;
    if (sizes[x] < sizes[y])
      std::swap(x, y);

    par[y] = x;
    sizes[x] += sizes[y];
  }
  int size(int x) { return sizes[root(x)]; }
};

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int n, m, q;
  cin >> n >> m >> q;
  vector<pii> a, b;
  vi used(n);
  REP(i, q) {
    int u, v, c;
    cin >> u >> v >> c;
    ; used[u] = 1;
    used[v] = 1;
    if (c == 0) {
      a.push_back({u, v});
    } else {
      b.push_back({u, v});
    }
  }
  queue<int> unused;
  REP(i, n)if (used[i] == 0)unused.push(i);
  UnionFind uf(n);
  REP(i, b.size()) { uf.unite(b[i].first, b[i].second); }
  map<int, ll> cnt;
  REP(i, n) cnt[uf.root(i)]++;
  ll tmax = 0, tmin = 0;
  bool ok = true;
  ll msz = 0, root = 0;
  vi cand;
  for (auto &&a : cnt) {
    if (chmax(msz, a.second)) {
      root = a.first;
    }
    if (a.second == 2)cand.push_back(a.first);
    if (a.second > 1)
      tmin += a.second;
    tmax += a.second * (a.second - 1) / 2;
  }

  if (msz == 2 && cand.size() == 1) {
    if (unused.empty())ok = false;
    else {
      int p = unused.front(); unused.pop();
      uf.unite(p, root);
      cand.clear();
    }
  }
  REP(i, cand.size()) {
    if (uf.root(cand[i]) == uf.root(root))continue;
    uf.unite(cand[i], root);
    tmin += 2;
    tmax += 2 * msz;
    msz += 2;
  }
  map<int, ll> cnt2;
  REP(i, n)cnt2[uf.root(i)]++;
  int nn = cnt2.size();
  map<int, int> mp, rmp;
  vi sz(nn);
  {
    int i = 0;
    for (auto&& a : cnt2) {
      mp[a.first] = i;
      rmp[i] = a.first;
      sz[i] = a.second;
      i++;
    }

  }
  UnionFind uf2(nn);
  

  REP(i, a.size()) {
    int uu = mp[uf.root(a[i].first)], vv = mp[uf.root(a[i].second)];
    if (uf2.same(uu, vv))ok = false;
    uf2.unite(uu, vv);
    tmin++;
    tmax++;
  }
  map<int, ll> cnt3;
  REP(i, nn) cnt3[uf2.root(i)]++;
  for (auto &&a : cnt3) {
    if (a.second == 1) {
      tmin++;
      tmax += msz * sz[a.first];
      msz += sz[a.first];
    }
  }
  if (tmin < m || m > tmax)
    ok = false;
  cout << (ok ? "Yes" : "No") << endl;
}