#include using namespace std; #define rep(i,m,n) for(int (i)=(int)(m);(i)<(int)(n);(i)++) #define rep2(i,m,n) for(int (i)=(int)(n)-1;(i)>=(int)(m);(i)--) #define REP(i,n) rep(i,0,n) #define REP2(i,n) rep2(i,0,n) #define FOR(i,c) for(decltype((c).begin())i=(c).begin();i!=(c).end();++i) #define ll long long #define ull unsigned long long #define all(hoge) (hoge).begin(),(hoge).end() #define en '\n' typedef pair P; constexpr long long INF = 1LL << 60; constexpr int INF_INT = 1 << 25; typedef vector Array; typedef vector Matrix; template using vec = vector; template using vvec = vector>; //constexpr long long MOD = (ll) 1e9+7; constexpr long long MOD = 998244353; template inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; } template inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; } struct Edge { int to, cap, rev; Edge(int _to, int _cap, int _rev) { to = _to; cap = _cap; rev = _rev; } }; typedef vector Edges; typedef vector Graph; void add_edge(Graph& G, int from, int to, int cap, bool revFlag, int revCap) { G[from].push_back(Edge(to, cap, G[to].size())); if (revFlag)G[to].push_back(Edge(from, revCap, G[from].size() - 1)); } //強連結成分分解 class SCC{ Graph g,rg; vector cmp,used,vs; int size; public: SCC(Graph _g):g(_g),rg(g.size()),cmp(g.size(),-1),used(g.size(),false){ REP(i,g.size()){ for(auto e:g[i]){ add_edge(rg,e.to,i,1,false,0);//逆辺のグラフ } } REP(i,g.size()){ if(!used[i]) dfs(i); } int k=0; REP(i,vs.size()){ ll v=vs[vs.size()-1-i]; if(used[v]){ rdfs(v,k); k++; } } size=k; } void dfs(int v){ //帰りがけ順に番号を振る used[v]=true; for(auto e:g[v]){ if(!used[e.to]) dfs(e.to); } vs.push_back(v); } void rdfs(int v, int k){ //通ることができた頂点に番号を振る used[v]=false; cmp[v]=k; for(auto e:rg[v]){ if(used[e.to]) rdfs(e.to,k); } } int getSize(){ return size; } int group(int v){ return cmp[v]; } Graph rebuild(){ //縮約したグラフを返す Graph ret(size); REP(i,g.size()){ int u=cmp[i]; for(auto e:g[i]){ int v=cmp[e.to]; if(u==v) continue; cout< data; int num; public: UnionFind(int size) : data(size, -1), num(size) { } bool unionSet(int x, int y) { x = root(x); y = root(y); if (x != y) { if (data[y] < data[x]) swap(x, y); data[x] += data[y]; data[y] = x; num--; } return x != y; } bool findSet(int x, int y) { return root(x) == root(y); } int root(int x) { return data[x] < 0 ? x : data[x] = root(data[x]); } int size(int x) { return -data[root(x)]; } int numSet() { return num; } }; void solve() { ll n,m; cin>>n>>m; Graph g(n); vec

ab; UnionFind uni(n); bool flag=false; REP(i,m){ ll a,b,c; cin>>a>>b>>c; a--;b--; if(uni.findSet(a,b)) flag=true; if(c==1){ add_edge(g,a,b,1,true,1); uni.unionSet(a,b); }else{ add_edge(g,a,b,1,false,1); ab.push_back({a,b}); } } if(flag){ cout<<"Yes"<> t; REP(i, t) solve(); return 0; }