#include <bits/stdc++.h>
using namespace std;
template <class T, class U>
void maximize(T &x, U y) {
  if (x < y) x = y;
}
template <class T, class U>
void minimize(T &x, U y) {
  if (x > y) x = y;
}
template <class T>
T Abs(T x) {
  return (x < (T)0 ? -x : x);
}
template <class T>
T safe_sqrt(T x) {
  return sqrt(max((T)0, x));
}
template <class T, class U, class V>
T addmod(T x, U k, V mod) {
  return ((x + k) % mod + mod) % mod;
}
template <class T, class U, class V>
T submod(T x, U k, V mod) {
  return ((x - k) % mod + mod) % mod;
}
template <class T, class U, class V>
T mulmod(T x, U k, V mod) {
  return (long long)x * k % mod;
}
namespace task {
const int N = 1e2 + 2;
bitset<N> bs[N];
int n, m, cnt;
int par[N];
int findp(int u) { return (u == par[u] ? u : par[u] = findp(par[u])); }
void join(int u, int v) {
  u = findp(u), v = findp(v);
  par[v] = u;
}
void solve() {
  scanf("%d%d", &n, &m);
  for (int k, la, i = 1; i <= n; ++i) {
    scanf("%d", &k);
    cnt += k;
    while (k--) scanf("%d", &la), bs[i][la] = true;
  }
  if (!cnt) printf("%d", n), exit(0);
  for (int i = 1; i <= n; ++i) par[i] = i;
  for (int i = 1; i <= n; ++i)
    for (int j = 1; j <= n; ++j)
      if (i - j)
        for (int k = 0; k <= 100; ++k)
          if (bs[i][k] and bs[j][k]) {
            join(i, j);
            break;
          }
  int ans = 0;
  for (int i = 1; i <= n; ++i) ans += (i == par[i]);
  printf("%d", ans - 1);
}
}  // namespace task
int main(void) { task::solve(); }
