#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=int(1e6+5);
typedef long long LL;
int n,k;
LL m;
int fa[MAXN];
struct edge {
    int u,v;
    edge() {};
    edge(int U,int V) {u=U,v=V;}
};
vector<edge>G;
int Find(int u) {
    if(u==fa[u])
        return u;
    return fa[u]=Find(fa[u]);
}
void Union(int u,int v) {
    int fu=Find(u),fv=Find(v);
    if(fu!=fv)
        fa[fu]=fv;
    return;
}
int main()
{
    //freopen("tour.in","r",stdin);
    //freopen("tour.out","w",stdout);
    int u,v,op;
    scanf("%d%lld%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=k;i++) {
        scanf("%d%d%d",&u,&v,&op);
        u++,v++;
        if(op==0)
            Union(u,v);
        else
            G.push_back(edge(u,v));
    }
    int cnt=0;
    for(int i=1;i<=n;i++)
        if(Find(i)==i)
            cnt++;
    LL mx=(LL)(cnt-1)*cnt/2+n-cnt;
    LL mi=(LL)(G.size()?n:n-1);
    if(mx<m||mi>m) {
        puts("No");
        return 0;
    }
    for(int i=0;i<G.size();i++)
        if(Find(G[i].u)==Find(G[i].v)) {
            puts("No");
            return 0;
        }
    puts("Yes");
}

### Prompt

Create a solution in Cpp for the following problem:

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`.

Examples

Input

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


Output

Yes


Input

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


Output

No


Input

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


Output

No

### Response

```cpp
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=int(1e6+5);
typedef long long LL;
int n,k;
LL m;
int fa[MAXN];
struct edge {
    int u,v;
    edge() {};
    edge(int U,int V) {u=U,v=V;}
};
vector<edge>G;
int Find(int u) {
    if(u==fa[u])
        return u;
    return fa[u]=Find(fa[u]);
}
void Union(int u,int v) {
    int fu=Find(u),fv=Find(v);
    if(fu!=fv)
        fa[fu]=fv;
    return;
}
int main()
{
    //freopen("tour.in","r",stdin);
    //freopen("tour.out","w",stdout);
    int u,v,op;
    scanf("%d%lld%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        fa[i]=i;
    for(int i=1;i<=k;i++) {
        scanf("%d%d%d",&u,&v,&op);
        u++,v++;
        if(op==0)
            Union(u,v);
        else
            G.push_back(edge(u,v));
    }
    int cnt=0;
    for(int i=1;i<=n;i++)
        if(Find(i)==i)
            cnt++;
    LL mx=(LL)(cnt-1)*cnt/2+n-cnt;
    LL mi=(LL)(G.size()?n:n-1);
    if(mx<m||mi>m) {
        puts("No");
        return 0;
    }
    for(int i=0;i<G.size();i++)
        if(Find(G[i].u)==Find(G[i].v)) {
            puts("No");
            return 0;
        }
    puts("Yes");
}

```