#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int MAXN = 1e6+5;
#define all(x) x.begin(), x.end()
#define sz(x) (int)x.size()
#define mk make_pair
#define pb push_back
#define fr first
#define sc second
int u[MAXN], v[MAXN], at[MAXN];
vi vise, visv, path, ans;
set<int> S;
vector<vi> edges;
void dfs(int ed, int walk) {
vise[ed] = walk;
int no = v[ed];
if(visv[no] == -1 or visv[no] == at[ed]) return;
path.pb(ed);
S.insert(ed);
for(auto viz : edges[no]) {
if(at[viz] == at[ed]) continue;
if(vise[viz] == 0) {
dfs(viz, walk);
if(!ans.empty()) return;
continue;
}
if(vise[viz] != walk) continue;
if(!S.count(viz)) continue;
ans = {viz};
while(path.back() != viz) {
ans.pb(path.back());
path.pop_back();
}
reverse(all(ans));
return;
}
if(visv[no] == 0) visv[no] = at[ed];
else visv[no] = -1;
path.pop_back();
S.erase(ed);
}
void solve() {
int n, m;
cin >> n >> m;
edges.clear();
edges.resize(n+1);
for(int i = 1; i <= m; i++) {
cin >> u[i] >> v[i] >> at[i];
edges[u[i]].pb(i);
}
vise.clear();
vise.resize(m+1);
visv.clear();
visv.resize(n+1);
path.clear();
ans.clear();
for(int i = 1; i <= m and ans.empty(); i++)
if(!vise[i]) dfs(i, i);
if(!ans.empty()) {
cout << "YES\n";
cout << sz(ans) << " ";
for(auto it : ans) cout << it << " ";
cout << "\n";
}
else cout << "NO\n";
}
int main() {
int t;
cin >> t;
while(t--) solve();
}