// Problem: C. Learning Languages
// Contest: Codeforces - Codeforces Round 170 (Div. 2)
// URL: https://codeforces.com/contest/278/problem/C
// Memory Limit: 256 MB
// Time Limit: 2000 ms
/*
Author: MikiMiku
*/
#include <bits/stdc++.h>
using namespace std;
/* DEBUGGING */
template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
template<typename T_container, typename T = typename enable_if<!is_same<T_container, string>::value, typename T_container::value_type>::type> ostream& operator<<(ostream &os, const T_container &v) { os << '{'; string sep; for (const T &x : v) os << sep << x, sep = ", "; return os << '}'; }
void dbg_out() { cerr << endl; }
template<typename Head, typename... Tail> void dbg_out(Head H, Tail... T) { cerr << ' ' << H; dbg_out(T...); }
#ifdef LOCAL
#define dbg(...) cerr << "(" << #__VA_ARGS__ << "):", dbg_out(__VA_ARGS__)
#else
#define dbg(...)
#endif
/* CONTAINER SHORTCUT */
#define sza(x) ((int)x.size())
#define all(a) (a).begin(), (a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define pb push_back
#define eb emplace_back
#define mp make_pair
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define ordered_set tree<int, null_type,less<int>, rb_tree_tag,tree_order_statistics_node_update>
/* GLOBAL OVERWRITE */
//#define int long long
#define endl '\n'
/* BIT MANIPULATION */
#define isOn(S, j) (S & (1 << j))
#define setBit(S, j) (S |= (1 << j))
#define clearBit(S, j) (S &= ~(1 << j))
#define toggleBit(S, j) (S ^= (1 << j))
#define LSB(S) (S & (-S))
#define setAll(S, n) (S = (1 << n) - 1)
#define modulo(S, N) ((S) & (N - 1)) // returns S % N, where N is a power of 2
#define isPowerOfTwo(S) (!(S & (S - 1)))
#define nearestPowerOfTwo(S) ((int)pow(2.0, (int)((log((double)S) / log(2.0)) + 0.5)))
#define turnOffLastBit(S) ((S) & (S - 1))
#define turnOnLastZero(S) ((S) | (S + 1))
#define turnOffLastConsecutiveBits(S) ((S) & (S + 1))
#define turnOnLastConsecutiveZeroes(S) ((S) | (S - 1))
/* GEOMETRY */
typedef complex<double> Point;
/* TYPE RE-DEFINE */
typedef unsigned long long ull;
typedef long long ll;
typedef long double ld;
/* CONSTANT */
const int MAX_N = 1e5 + 5;
const ll MOD = 1e9 + 7;
const int FMOD = 998244353;
const ll INF = 1e9;
const ld EPS = 1e-9;
const double PI=acos(-1);
/* SHORTCUT */
#define fi first
#define se second
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<int> vi;
typedef map<int,int> mii;
/* RANDOM */
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
#define SHUF(v) shuffle(all(v), rng);
//FLOAT PRECISION SETTINGS
/*
cout.setf(ios::fixed,ios::floatfield);
cout.precision(3);
*/
//FILE IO
void setIO(string s) {
freopen((s + ".in").c_str(), "r", stdin);
freopen((s + ".out").c_str(), "w", stdout);
}
//........................................................................
int n, m;
vector<int> adjList[107];
bool speak[107][107];
set<int> comsp[107];
bool visited[107]; int id;
void dfs(int u) {
visited[u] = true;
for(int i = 1; i <= m; ++i) {
if(speak[u][i]) comsp[id].insert(i);
}
for(auto v : adjList[u]) {
if(!visited[v]) dfs(v);
}
}
signed main() {
ios_base::sync_with_stdio(0);cin.tie(nullptr); cout.tie(nullptr);
cin >> n >> m;
memset(speak, 0, sizeof(speak));
for(int i = 0; i < n; ++i) {
int ki;
cin >> ki;
for(int j = 0; j < ki; ++j) {
int li; cin >> li;
speak[i][li] = true;
}
}
for(int i = 1; i <= m; ++i) {
for(int j = 0; j < n; ++j) {
for(int k = j + 1; k < n; ++k) {
if(speak[j][i] && speak[k][i]) {
adjList[j].pb(k);
adjList[k].pb(j);
}
}
}
}
int com = 0;
memset(visited, 0, sizeof(visited));
id = 0;
for(int i = 0; i < n; ++i) {
if(!visited[i]) dfs(i), com++, id++;
}
int notempty = 0;
int ans = 0;
for(int i = 0; i < id; ++i) {
//dbg(comsp[i]);
if(sza(comsp[i]) == 0) ans++;
else notempty++;
}
if(notempty > 0) ans += notempty - 1;
cout << ans << endl;
return 0;
}
461. Hamming Distance | 1748. Sum of Unique Elements |
897. Increasing Order Search Tree | 905. Sort Array By Parity |
1351. Count Negative Numbers in a Sorted Matrix | 617. Merge Two Binary Trees |
1450. Number of Students Doing Homework at a Given Time | 700. Search in a Binary Search Tree |
590. N-ary Tree Postorder Traversal | 589. N-ary Tree Preorder Traversal |
1299. Replace Elements with Greatest Element on Right Side | 1768. Merge Strings Alternately |
561. Array Partition I | 1374. Generate a String With Characters That Have Odd Counts |
1822. Sign of the Product of an Array | 1464. Maximum Product of Two Elements in an Array |
1323. Maximum 69 Number | 832. Flipping an Image |
1295. Find Numbers with Even Number of Digits | 1704. Determine if String Halves Are Alike |
1732. Find the Highest Altitude | 709. To Lower Case |
1688. Count of Matches in Tournament | 1684. Count the Number of Consistent Strings |
1588. Sum of All Odd Length Subarrays | 1662. Check If Two String Arrays are Equivalent |
1832. Check if the Sentence Is Pangram | 1678. Goal Parser Interpretation |
1389. Create Target Array in the Given Order | 1313. Decompress Run-Length Encoded List |