#include <bits/stdc++.h>

using namespace std;

#define pb push_back
#define mp make_pair
#define mt make_tuple
#define fi first
#define se second
#define all(a) (a).begin(),(a).end()
#define endl "\n"
#define rep(i, a, b) for (auto (i) = (a); (i) < (b); (i)++)
#define rrep(i, a, b) for (auto (i) = (a); (i) > (b); (i)--)

#define aim_cpo do{ios::sync_with_stdio(false);\
cin.tie(nullptr);cout.precision(12);cout<<fixed;}while(0)

#define LOCAL_INPUT do{FILE *stream1;\
stream1=freopen("/Users/aim_cpo/CLionProjects/competitive/in.txt","r",stdin);\
if(stream1==nullptr)return 0;}while(0)
#define LOCAL_OUTPUT do{FILE *stream2;\
stream2 = freopen("out.txt", "w", stdout);\
if (stream2 == nullptr) return 0;}while(0)

#ifdef LOCAL_DEFINE
#define show(x) cerr << #x << " = " << (x) << endl
#define showV(v, n) do{\
for(int _i_t_e_=0; _i_t_e_<(n);_i_t_e_++)\
cerr<<"("<<_i_t_e_<<" = "<<(v)[_i_t_e_]<<") ";\
cerr<<endl;}while(0)
#define showA(a, n) do{\
for(int _i_t_e_=0;_i_t_e_<(n);_i_t_e_++)\
cerr<<"("<<_i_t_e_<<" = "<<(a)[_i_t_e_]<<") ";\
cerr<<endl;}while(0)
#define showA2(a, n, m) do{\
for(int _i_t_e_=0;_i_t_e_<(n);_i_t_e_++){\
for(int _i_t_e_2=0;_i_t_e_2<(m);_i_t_e_2++){\
cerr<<"("<<_i_t_e_<<", "<<_i_t_e_2<<" = "<<(a)[_i_t_e_][_i_t_e_2]<<") ";\
}cerr<<endl;}cerr<<endl;}while(0)
#else
#define show(x)
#define showV(v, n)
#define showA(a, n)
#define showA2(a, n, m)
#endif

typedef long long ll;
typedef unsigned long long ull;

constexpr const int INT_INF=0x3f3f3f3f; //1061109567
constexpr const ll LL_INF=0x3f3f3f3f3f3f3f3f; //4557430888798830399

template <typename T> bool chmin(T &a, T b){return a>b?(a=b,true):false;}
template <typename T> bool chmax(T &a, T b){return a<b?(a=b,true):false;}
template <typename T> void ln(T i, T n){cout<<(i==n-1?"\n":" ");}
template <typename T, typename S>
ostream &operator<<(ostream &out,const pair<T, S> &pair1){
  out<<'('<<pair1.fi<<", "<<pair1.se<<')';return out;}

// INT
#define GCD(a, b) __gcd(a, b)
template <typename T> T LCM(T a, T b) {return a / GCD(a, b) * b;}
template <typename T> T EXTGCD(T a, T b, T& x, T& y) {
  T d = a;
  if (b != 0) {d=EXTGCD(b,a%b,y,x);y-=(a/b)*x;}
  else x=1,y=0;
  return d;
}
template <typename T> bool is_prime(T a) {
  for(int i=2;i*i<=a;i++)if(a%i==0)return 1;
  return 0;
}

// MOD
ll MOD = 1000000000L + 7L;
#define add(a, b) ((a % MOD) + (b % MOD)) % MOD
#define mul(a, b) ((a % MOD) * (b % MOD)) % MOD
#define sub(a, b) ((a % MOD) + MOD - (b % MOD)) % MOD
template <typename T> T mod_inverse(T a, T mod, bool prime){ // if mod is prime, "prime" is true.
  if(prime){
    T tmp=mod-2,now=a,res=1;while(tmp){if(tmp&1)res=mul(res,now);now=mul(now,now);tmp>>=1;}
    return res;
  }else{T x,y;EXTGCD(a,mod,x,y);return (mod+x%mod)%mod;}
}
#define divide(a, b) ((a % MOD) * (mod_inverse(b, MOD, true))) % MOD

//LLの数値をつかう時は最後にLをつける癖をつけよう
//
//  ┏┓┏┓　┓　┏┓
//  ┏┛┃┃　┃　┗┫
//  ┗┛┗┛　┻　┗┛
//
//   謹┃賀┃新┃年┃
//   ━┛━┛━┛━┛
//WWWWWWWWWWWWWWWWWWWWWW

class UnionFind
{
public:
  explicit UnionFind(int _n) : n(_n)
  {
    par.resize(static_cast<unsigned long>(_n));
    rank.resize(static_cast<unsigned long>(_n));
    sizes.resize(static_cast<unsigned long>(_n));
    for (int i = 0; i < _n; i++)
    {
      par[i] = i;
      rank[i] = 0;
      sizes[i] = 1;
    }
  }

  //親ノードを見つけます
  int find(int a)
  {
    if (par[a] == a)
      return a;
    return par[a] = find(par[a]);
  }

  //aとbが同じグループかの判定
  bool same(int a, int b)
  {
    return find(a) == find(b);
  }

  //aとbを同じグループにします
  void unite(int a, int b)
  {
    link(find(a), find(b));
  }

  //aが属するグループの要素数を求めます
  int size(int a)
  {
    return sizes[find(a)];
  }

  //全体がどのグループに属しているかがわかります
  void view()
  {
    for (int i = 0; i < n; i++)
    {
      cout << " par"
           << "[" << i << "]=" << par[i] << ((i == n - 1) ? "\n" : ",");
    }
    for (int i = 0; i < n; i++)
    {
      cout << "size"
           << "[" << i << "]=" << sizes[i] << ((i == n - 1) ? "\n" : ",");
    }
    cout << endl;
  }

private:
  void link(int a, int b)
  {
    if (same(a, b))
      return;
    if (rank[a] > rank[b])
    {
      par[b] = a;
      sizes[a] += sizes[b];
      sizes[b] = 0;
    }
    else
    {
      par[a] = b;
      if (rank[a] == rank[b])
        rank[b]++;
      sizes[b] += sizes[a];
      sizes[a] = 0;
    }
  }
  int n;
  vector<int> par;
  vector<int> rank;
  vector<int> sizes;
};

int n, m;
vector<int> L[100001];

int main() {
  aim_cpo; // インタラクティブのときは消すように.
#ifdef LOCAL_DEFINE
  LOCAL_INPUT; // インタラクティブのときは消すように.
//  LOCAL_OUTPUT; // ファイルに出力したいときのみ
  show(MOD);
#endif
  // テキトー考察
  //
  // 言語ごとに誰がその言語を喋れるかを見ていく
  // 当然、同じ言語が喋れる人はコミュニケーションを取れる
  // 言語ごとに誰と誰がコミュニケーションを取れるかをUnionFindなど使って、グループ分けしていく
  // 最終的にグループのサイズがNになっていたらYES
  cin >> n >> m;
  rep(i, 0, n) {
    int k; cin >> k;
    rep(j, 0, k) {
      int a; cin >> a; a--;
      L[a].push_back(i);
    }
  }
  UnionFind uf(n);
  rep(i, 0, m) {
    rep(j, 1, (int)L[i].size()) {
      uf.unite(L[i][j], L[i][j - 1]);
    }
  }
  if (uf.size(0) == n) {
    cout << "YES" << endl;
  } else cout << "NO" << endl;
#ifdef  LOCAL_DEFINE
  cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << "s." << endl;
#endif
  return 0;
}

Measured memory_bytes: 4988