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)

#pragma GCC target("avx2")
#pragma GCC optimize("O3")

# include <x86intrin.h>
# 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;
 
template<typename T> using ordered_set = tree <T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define _USE_MATH_DEFINES_
#define ll long long
#define ld long double
#define Accepted 0
#define pb push_back
#define mp make_pair
#define sz(x) (int)(x.size())
#define every(x) x.begin(),x.end()
#define F first
#define S second
#define lb lower_bound
#define ub upper_bound
#define For(i,x,y)  for (ll i = x; i <= y; i ++) 
#define FOr(i,x,y)  for (ll i = x; i >= y; i --)
#define SpeedForce ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0)
// ROAD to...                                                                                                                                                                                                                Red

inline void Input_Output () {
	//freopen(".in", "r", stdin);
   //freopen(".out", "w", stdout);
}

const double eps = 0.000001;
const ld pi = acos(-1);
const int maxn = 1e7 + 9;
const int mod = 1e9 + 7;
const ll MOD = 1e18 + 9;
const ll INF = 1e18 + 123;
const int inf = 2e9 + 11;
const int mxn = 1e6 + 9;
const int N = 6e5 + 123;                                          
const int M = 22;
const int pri = 997;
const int Magic = 2101;

const int dx[] = {-1, 0, 1, 0};
const int dy[] = {0, -1, 0, 1};
 
ll n, m, k;
vector < int > g[N];
int p[N];
int sz[N];

int get (int x) {
	if (p[x] != x) p[x] = get(p[x]);
	return p[x];
}

int u[N];
set < int > all;
vector < int > now;

void dfs (int v) {
	now.pb(v);

	u[v] = 1;
	for (auto to : g[v]) if (!u[to]) {
		dfs(to);
		u[v] += u[to];
	}
}

int main () {
   SpeedForce;
	cin >> n >> m >> k;

	for (int i = 1; i <= n; i ++) p[i] = i, sz[i] = 1;

	ll mx = 0;
	int mn = 0;

	for (int i = 1; i <= k; i ++) {
		int a, b, c;
		cin >> a >> b >> c;
		if (c) {
			g[a].pb(b);
			g[b].pb(a);
		} else {
			a = get(a);
			b = get(b);
			if (sz[a] > sz[b]) swap(a, b);
			p[a] = b;

			sz[b] += sz[a];

			mn ++;
			mx += sz[b] - 1; 
		}
	}

	for (int i = 1; i <= n; i ++) if (p[i] == i) {
		all.insert(i);
	}

	
	for (int i = 1; i <= m; i ++) if (g[i].size()) {
		now.clear();
		dfs(i);	
		if (u[i] == 2) {
			for (auto e : now) {	
				all.erase(get(e));
			}
			if (all.empty()) {
				cout << "No";
				exit(0);
			}
			mn += 2;
			mx += (int)all.size() * 2ll;
			for (auto e : now) {	
				all.insert(get(e));
			}
		} else {
			mn += u[i];
			mx += u[i] * (ll)(u[i] - 1) / 2ll;
		}
	}

	if (mn <= m && m <= mx)
		cout << "Yes";
	else
		cout << "No";

   return Accepted;
}

// B...a