#include using namespace std; const int MAX_N = 1e6 + 5; int parent[MAX_N], tag[MAX_N]; vector comp[MAX_N]; int root(int x) { return parent[x] < 0 ? x : (parent[x] = root(parent[x])); } void merge(int x, int y) { x = root(x); y = root(y); if (x == y) return; if (parent[x] > parent[y]) swap(x, y); parent[x] += parent[y]; parent[y] = x; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0); int n, m; cin >> n >> m; vector> v(1+n); for (int i = 1; i <= n; ++i) { int k; cin >> k; while (k--) { int x; cin >> x; v[i].push_back(x); } } for (int i = 1; i <= m; ++i) parent[i] = -1; vector> prs; for (int i = 1; i <= n; ++i) prs.emplace_back(v[i].size(), i); sort(prs.begin(), prs.end()); for (auto [sz, i] : prs) { // cout << " at " << i << endl; vector compSeen; for (int j : v[i]) { int rt = root(j); if (comp[rt].empty()) { compSeen.push_back(rt); } comp[rt].push_back(j); } for (int c : compSeen) { // cout << " Have component root " << c << " vals " << comp[c].size() << " of " << -parent[c] << endl; if (-parent[c] != comp[c].size()) { // found non-subset intersection cout << "YES\n" << i << ' ' << tag[c] << '\n'; return 0; } } // unite if (!compSeen.empty()) { int r = compSeen.back(); comp[r].clear(); compSeen.pop_back(); while (!compSeen.empty()) { comp[compSeen.back()].clear(); int x = compSeen.back(); compSeen.pop_back(); merge(r, x); r = root(r); } tag[r] = i; } } cout << "NO\n"; return 0; }