#pragma GCC optimize ("Ofast") #include using namespace std; void *wmem; char memarr[96000000]; template inline void walloc1d(T **arr, int x, void **mem = &wmem){ static int skip[16] = {0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; (*mem) = (void*)( ((char*)(*mem)) + skip[((unsigned long long)(*mem)) & 15] ); (*arr)=(T*)(*mem); (*mem)=((*arr)+x); } inline int my_getchar_unlocked(){ static char buf[1048576]; static int s = 1048576; static int e = 1048576; if(s == e && e == 1048576){ e = fread_unlocked(buf, 1, 1048576, stdin); s = 0; } if(s == e){ return EOF; } return buf[s++]; } inline void rd(int &x){ int k; int m=0; x=0; for(;;){ k = my_getchar_unlocked(); if(k=='-'){ m=1; break; } if('0'<=k&&k<='9'){ x=k-'0'; break; } } for(;;){ k = my_getchar_unlocked(); if(k<'0'||k>'9'){ break; } x=x*10+k-'0'; } if(m){ x=-x; } } struct MY_WRITER{ char buf[1048576]; int s; int e; MY_WRITER(){ s = 0; e = 1048576; } ~MY_WRITER(){ if(s){ fwrite_unlocked(buf, 1, s, stdout); } } } ; MY_WRITER MY_WRITER_VAR; void my_putchar_unlocked(int a){ if(MY_WRITER_VAR.s == MY_WRITER_VAR.e){ fwrite_unlocked(MY_WRITER_VAR.buf, 1, MY_WRITER_VAR.s, stdout); MY_WRITER_VAR.s = 0; } MY_WRITER_VAR.buf[MY_WRITER_VAR.s++] = a; } inline void wt_L(char a){ my_putchar_unlocked(a); } inline void wt_L(const char c[]){ int i=0; for(i=0;c[i]!='\0';i++){ my_putchar_unlocked(c[i]); } } template inline void arrInsert(const int k, int &sz, S a[], const S aval){ int i; sz++; for(i=sz-1;i>k;i--){ a[i] = a[i-1]; } a[k] = aval; } template inline void arrInsert(const int k, int &sz, S a[], const S aval, T b[], const T bval){ int i; sz++; for(i=sz-1;i>k;i--){ a[i] = a[i-1]; } for(i=sz-1;i>k;i--){ b[i] = b[i-1]; } a[k] = aval; b[k] = bval; } template inline void arrInsert(const int k, int &sz, S a[], const S aval, T b[], const T bval, U c[], const U cval){ int i; sz++; for(i=sz-1;i>k;i--){ a[i] = a[i-1]; } for(i=sz-1;i>k;i--){ b[i] = b[i-1]; } for(i=sz-1;i>k;i--){ c[i] = c[i-1]; } a[k] = aval; b[k] = bval; c[k] = cval; } template inline void arrInsert(const int k, int &sz, S a[], const S aval, T b[], const T bval, U c[], const U cval, V d[], const V dval){ int i; sz++; for(i=sz-1;i>k;i--){ a[i] = a[i-1]; } for(i=sz-1;i>k;i--){ b[i] = b[i-1]; } for(i=sz-1;i>k;i--){ c[i] = c[i-1]; } for(i=sz-1;i>k;i--){ d[i] = d[i-1]; } a[k] = aval; b[k] = bval; c[k] = cval; d[k] = dval; } struct unionFind{ int *d; int N; int M; inline void malloc(const int n){ d = (int*)std::malloc(n*sizeof(int)); M = n; } inline void malloc(const int n, const int fg){ d = (int*)std::malloc(n*sizeof(int)); M = n; if(fg){ init(n); } } inline void free(void){ std::free(d); } inline void walloc(const int n, void **mem=&wmem){ walloc1d(&d, n, mem); M = n; } inline void walloc(const int n, const int fg, void **mem=&wmem){ walloc1d(&d, n, mem); M = n; if(fg){ init(n); } } inline void init(const int n){ int i; N = n; for(i=(0);i<(n);i++){ d[i] = -1; } } inline void init(void){ init(M); } inline int get(int a){ int t = a; int k; while(d[t]>=0){ t=d[t]; } while(d[a]>=0){ k=d[a]; d[a]=t; a=k; } return a; } inline int connect(int a, int b){ if(d[a]>=0){ a=get(a); } if(d[b]>=0){ b=get(b); } if(a==b){ return 0; } if(d[a] < d[b]){ d[a] += d[b]; d[b] = a; } else{ d[b] += d[a]; d[a] = b; } return 1; } inline int operator()(int a){ return get(a); } inline int operator()(int a, int b){ return connect(a,b); } inline int& operator[](const int a){ return d[a]; } inline int size(int a){ a = get(a); return -d[a]; } inline int sizeList(int res[]){ int i; int sz=0; for(i=(0);i<(N);i++){ if(d[i]<0){ res[sz++] = -d[i]; } } return sz; } } ; template int coordcomp_L(int n, T arr[], int res[] = NULL, void *mem = wmem){ int i; int k = 0; pair *r; walloc1d(&r, n, &mem); for(i=(0);i<(n);i++){ r[i].first = arr[i]; r[i].second = i; } sort(r, r+n); if(res != NULL){ for(i=(0);i<(n);i++){ if(i && r[i].first != r[i-1].first){ k++; } res[r[i].second] = k; } } else{ for(i=(0);i<(n);i++){ if(i && r[i].first != r[i-1].first){ k++; } arr[r[i].second] = k; } } return k+1; } template int coordcomp_L(int n1, T arr1[], int n2, T arr2[], int res1[] = NULL, int res2[] = NULL, void *mem = wmem){ int i; int k = 0; pair *r; walloc1d(&r, n1+n2, &mem); for(i=(0);i<(n1);i++){ r[i].first = arr1[i]; r[i].second = i; } for(i=(0);i<(n2);i++){ r[n1+i].first = arr2[i]; r[n1+i].second = n1+i; } sort(r, r+n1+n2); for(i=(0);i<(n1+n2);i++){ if(i && r[i].first != r[i-1].first){ k++; } if(r[i].second < n1){ if(res1!=NULL){ res1[r[i].second] = k; } else{ arr1[r[i].second] = k; } } else{ if(res2!=NULL){ res2[r[i].second-n1] = k; } else{ arr2[r[i].second-n1] = k; } } } return k+1; } struct graph{ int N; int *es; int **edge; void setEdge(int N__, int M, int A[], int B[], void **mem = &wmem){ int i; N = N__; walloc1d(&es, N, mem); walloc1d(&edge, N, mem); for(i=(0);i<(N);i++){ es[i] = 0; } for(i=(0);i<(M);i++){ es[A[i]]++; es[B[i]]++; } for(i=(0);i<(N);i++){ walloc1d(&edge[i], es[i], mem); } for(i=(0);i<(N);i++){ es[i] = 0; } for(i=(0);i<(M);i++){ edge[A[i]][es[A[i]]++] = B[i]; edge[B[i]][es[B[i]]++] = A[i]; } } void setDirectEdge(int N__, int M, int A[], int B[], void **mem = &wmem){ int i; N = N__; walloc1d(&es, N, mem); walloc1d(&edge, N, mem); walloc1d(&edge[0], M, mem); for(i=(0);i<(N);i++){ es[i] = 0; } for(i=(0);i<(M);i++){ es[A[i]]++; } for(i=(0);i<(N);i++){ walloc1d(&edge[i], es[i], mem); } for(i=(0);i<(N);i++){ es[i] = 0; } for(i=(0);i<(M);i++){ edge[A[i]][es[A[i]]++] = B[i]; } } graph reverse(void **mem = &wmem){ int i; int j; int k; graph g; g.N = N; walloc1d(&g.es, N, mem); walloc1d(&g.edge, N, mem); for(i=(0);i<(N);i++){ g.es[i] = 0; } for(i=(0);i<(N);i++){ for(j=(0);j<(es[i]);j++){ g.es[edge[i][j]]++; } } for(i=(0);i<(N);i++){ walloc1d(&g.edge[i], g.es[i], mem); } for(i=(0);i<(N);i++){ g.es[i] = 0; } for(i=(0);i<(N);i++){ for(j=(0);j<(es[i]);j++){ k = edge[i][j]; g.edge[k][g.es[k]++] = i; } } return g; } inline int sccDFS(int num[], int st, int mx){ int i; int j; num[st]=-2; for(i=(0);i<(es[st]);i++){ j=edge[st][i]; if(num[j]==-1){ mx=sccDFS(num,j,mx); } } num[st]=mx; return mx+1; } int scc(int res[], void *mem = wmem){ int i; int j; int k; int ret=0; graph r; int *st; int st_size; int *num; int *nrv; r = reverse(&mem); walloc1d(&st, N, &mem); walloc1d(&num, N, &mem); walloc1d(&nrv, N, &mem); for(i=(0);i<(N);i++){ res[i] = num[i] = -1; } k = 0; for(i=(0);i<(N);i++){ if(num[i]==-1){ k = sccDFS(num,i,k); } } for(i=(0);i<(N);i++){ nrv[num[i]] = i; } for(k=N-1;k>=0;k--){ i=nrv[k]; if(res[i]>=0){ continue; } res[i]=ret; st_size=0; st[st_size++]=i; while(st_size){ i=st[--st_size]; for(j=(0);j<(r.es[i]);j++){ if(res[r.edge[i][j]]==-1){ res[r.edge[i][j]]=ret; st[st_size++]=r.edge[i][j]; } } } ret++; } return ret; } } ; int N; int M; int A[400000]; int B[400000]; int C[400000]; int n; int m; int a[400000]; int b[400000]; int scc[100000]; graph g; int vis[100000]; int solve(int n, int b = -1){ int Lj4PdHRW; if(vis[n]){ return 0; } vis[n] = 2; for(Lj4PdHRW=(0);Lj4PdHRW<(g.es[n]);Lj4PdHRW++){ auto &i = g.edge[n][Lj4PdHRW]; if(i==b){ continue; } if(vis[i]==2){ return 1; } if(solve(i, n)){ return 1; } } vis[n] = 1; return 0; } int main(){ int i; wmem = memarr; int k; unionFind uf; set> s0; set> s1; rd(N); rd(M); { int e98WHCEY; for(e98WHCEY=(0);e98WHCEY<(M);e98WHCEY++){ rd(A[e98WHCEY]);A[e98WHCEY] += (-1); rd(B[e98WHCEY]);B[e98WHCEY] += (-1); rd(C[e98WHCEY]);C[e98WHCEY] += (-1); } } for(i=(0);i<(M);i++){ if(C[i]==0){ s0.insert( make_pair(A[i], B[i]) ); if(s1.count(make_pair(A[i], B[i]))){ wt_L("Yes"); wt_L('\n'); return 0; } if(s1.count(make_pair(B[i], A[i]))){ wt_L("Yes"); wt_L('\n'); return 0; } } else{ s1.insert( make_pair(A[i], B[i]) ); if(s0.count(make_pair(A[i], B[i]))){ wt_L("Yes"); wt_L('\n'); return 0; } if(s0.count(make_pair(B[i], A[i]))){ wt_L("Yes"); wt_L('\n'); return 0; } if(s1.count(make_pair(B[i], A[i]))){ wt_L("Yes"); wt_L('\n'); return 0; } } } for(i=(0);i<(M);i++){ if(C[i]==0){ arrInsert(m,m,a,A[i],b,B[i]); } } g.setEdge(N,m,a,b); for(i=(0);i<(N);i++){ if(!vis[i]){ if(solve(i)){ wt_L("Yes"); wt_L('\n'); return 0; } } } uf.malloc(N, 1); for(i=(0);i<(M);i++){ if(C[i]==0){ uf(A[i],B[i]); } } m = 0; for(i=(0);i<(M);i++){ if(C[i]==1){ arrInsert(m,m,a,uf(A[i]),b,uf(B[i])); } } for(i=(0);i<(m);i++){ if(a[i]==b[i]){ wt_L("Yes"); wt_L('\n'); return 0; } } n =coordcomp_L(m,a,m,b); g.setDirectEdge(n,m,a,b); if(g.scc(scc) < n){ wt_L("Yes"); wt_L('\n'); return 0; } wt_L("No"); wt_L('\n'); return 0; } // cLay varsion 20200408-1 // --- original code --- // int N, M, A[4d5], B[4d5], C[4d5]; // // int n, m, a[4d5], b[4d5], scc[1d5]; // graph g; // // int vis[1d5]; // int solve(int n, int b = -1){ // if(vis[n]) return 0; // vis[n] = 2; // rep[g.edge[n]](i,g.es[n]){ // if(i==b) continue; // if(vis[i]==2) return 1; // if(solve(i, n)) return 1; // } // vis[n] = 1; // return 0; // } // // { // int k; // unionFind uf; // set> s0, s1; // rd(N,M,(A--,B--,C--)(M)); // // rep(i,M){ // if(C[i]==0){ // s0.insert( make_pair(A[i], B[i]) ); // if(s1.count(make_pair(A[i], B[i]))) wt("Yes"), return 0; // if(s1.count(make_pair(B[i], A[i]))) wt("Yes"), return 0; // } else { // s1.insert( make_pair(A[i], B[i]) ); // if(s0.count(make_pair(A[i], B[i]))) wt("Yes"), return 0; // if(s0.count(make_pair(B[i], A[i]))) wt("Yes"), return 0; // if(s1.count(make_pair(B[i], A[i]))) wt("Yes"), return 0; // } // } // // rep(i,M) if(C[i]==0) arrInsert(m,m,a,A[i],b,B[i]); // g.setEdge(N,m,a,b); // rep(i,N) if(!vis[i]) if(solve(i)) wt("Yes"), return 0; // // uf.malloc(N, 1); // rep(i,M) if(C[i]==0) uf(A[i],B[i]); // // m = 0; // rep(i,M) if(C[i]==1) arrInsert(m,m,a,uf(A[i]),b,uf(B[i])); // rep(i,m) if(a[i]==b[i]) wt("Yes"), return 0; // n = coordcomp(m,a,m,b); // g.setDirectEdge(n,m,a,b); // if(g.scc(scc) < n) wt("Yes"), return 0; // // wt("No"); // }