#include #include #include using namespace std; typedef long long int ll; map, int> memo; //is X subset of Y //assume X is at most as big as Y and X/=Y //just check all elem of X if are in Y int isSubset(const vector> &users, int x, int y) { auto it = memo.find({x, y}); if (it != memo.end()) { return it->second; } if (users[x].size() * 10 > users[y].size()) { int i = 0; int result = 1; for (int xx: users[x]) { while (i < users[y].size() && users[y][i] < xx) { i++; } if (i >= users[y].size() || users[y][i] > xx) { result = 0; break; } } memo[{x, y}] = result; return result; } for (int xx: users[x]){ if (!std::binary_search(users[y].begin(), users[y].end(), xx)){ memo[{x, y}] = false; return false; } } memo[{x, y}] = true; return true; } vector> users; ll prime = 1000000007; ll num = 987659; ll myhash(ll id) { ll cur = 1; ll ret = 0; for (int i = 0; i < users[id].size(); ++i) { ret += (users[id][i] * cur) % prime; cur *= num; cur %= prime; } return ret; } int main() { ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m, k; cin >> n >> m; vector>> usersWithActivity(m + 1); users.resize(n); set> hashes; vector active(n, true); for (int i = 0; i < n; i++) { cin >> k; users[i].resize(k); for (int j = 0; j < k; j++) { cin >> users[i][j]; usersWithActivity[users[i][j]].emplace_back(k, i); } pairp ={k, myhash(i)}; if (hashes.count(p) == 0){ hashes.insert(p); } else { active[i] = false; } sort(users[i].begin(), users[i].end()); } for (int act = 0; act <= m; act++) { sort(usersWithActivity[act].begin(), usersWithActivity[act].end()); vector> uwa; for (auto [len, u]: usersWithActivity[act]){ if (active[u]) { uwa.emplace_back(len, u); } } for (int j = int(uwa.size()) - 2; j >= 0; j--) { if (uwa[j].first ==uwa[j + 1].first) { cout << "YES\n" << uwa[j].second + 1 << ' ' << uwa[j + 1].second + 1 << '\n'; return 0; } if (!isSubset(users, uwa[j].second, uwa[j + 1].second)) { cout << "YES\n" << uwa[j].second + 1 << ' ' << uwa[j + 1].second + 1 << '\n'; return 0; } } } cout << "NO\n"; return 0; }