#include <bits/stdc++.h>
#pragma warning(disable : 4786)
using namespace std;
vector<int> lang[105], adj[105];
int num;
bool visit[105];
int dfs(int node) {
  visit[node] = true;
  int ret = 1, i;
  for (i = 0; i < adj[node].size(); i++) {
    if (visit[adj[node][i]] == true) {
      continue;
    }
    ret += dfs(adj[node][i]);
  }
  return ret;
}
int main() {
  int n, m, i, flag, j, a, k, l, grp;
  while (scanf("%d%d", &n, &m) != EOF) {
    flag = 0;
    for (i = 1; i <= n; i++) {
      scanf("%d", &k);
      for (j = 1; j <= k; j++) {
        scanf("%d", &a);
        lang[i].push_back(a);
        flag = 1;
      }
    }
    if (flag == 0) {
      printf("%d\n", n);
      for (i = 1; i <= n; i++) {
        lang[i].clear();
      }
      continue;
    }
    for (i = 1; i <= n; i++) {
      for (j = i + 1; j <= n; j++) {
        flag = 0;
        for (k = 0; k < lang[i].size(); k++) {
          for (l = 0; l < lang[j].size(); l++) {
            if (lang[i][k] == lang[j][l]) {
              adj[i].push_back(j);
              adj[j].push_back(i);
              flag = 1;
              break;
            }
          }
          if (flag == 1) {
            break;
          }
        }
      }
    }
    for (i = 1; i <= n; i++) {
      visit[i] = false;
    }
    num = 0;
    grp = 0;
    for (i = 1; i <= n; i++) {
      if (num == n) {
        break;
      }
      if (visit[i] == true) {
        continue;
      }
      num += dfs(i);
      grp++;
    }
    printf("%d\n", grp - 1);
    for (i = 1; i <= n; i++) {
      lang[i].clear();
      adj[i].clear();
    }
  }
  return 0;
}
