#include <iostream>
#include <map>
#include <vector>
#include <cstring>
#include <utility>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <string>
#include <stack>
#include <set>
#include <deque>
#define mp make_pair
using namespace std;
int v[205],a[205],fa[205],n,m,k,ans;
int get(int x){
	if (x==fa[x]) return x;
	return fa[x]=get(fa[x]);
}
int main(){
	cin>>n>>m;
	for (int i=1;i<=m;i++) fa[i]=i;
	for (int i=1;i<=n;i++){
		cin>>k;
		if (!k) ans++;
		for (int j=1;j<=k;j++) cin>>a[j],v[a[j]]=1;
		for (int j=1;j<k;j++) fa[get(a[j])]=get(a[j+1]);
	}
	if (ans==n){
		cout<<n;
		return 0;
	}else{
		for (int i=1;i<=n;i++){
			if (v[i] && get(i)==i) ans++;
		}
		cout<<ans-1;
		return 0;
	}
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
vector<int>v[maxn];
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++){
            cin>>a[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                }
                if(o)
                    break;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            for(int j=0;j<n;j++){
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=1;
    for(int i=0;i<n;i++){
        if(a[i][0])
            dd=0;
    }
    ww+=d;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
vector<int>v[maxn];
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++){
            cin>>a[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                }
                if(o)
                    break;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            int hhh=mm[y];
            for(int j=0;j<n;j++){
                if(mm[j]==hhh)
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=0;
    for(int i=0;i<n;i++){
        if(a[i][0]==0)
            dd++;
    }
    if(dd==n)
        ww++;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=1000,maxm=1000*1000;
int n,m,a[maxn][maxn],mm[maxn],cnt,dd=1,ww,mark[maxn];
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        if(a[i][0])
            dd=0;
        for(int j=1;j<=a[i][0];j++)
            cin>>a[i][j];
    }
    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++)
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt++].S=j;
                        o=1;
                        break;
                    }
                if(o)
                    break;
            }
        }
    for(int i=0;i<=cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y])
            for(int j=0;j<n;j++)
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
    }
    for(int i=0;i<n;i++)
        mark[mm[i]]=1;
    for(int i=0;i<n;i++)
        ww+=mark[i];
    ww+=dd;
    cout<<--ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++){
            cin>>a[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                    }
                }
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            for(int j=0;j<n;j++){
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=1;
    for(int i=0;i<n;i++){
        if(a[i][0])
            dd=0;
    }
    ww+=dd;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
vector<int>v[maxn];
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++){
            cin>>a[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                }
                if(o)
                    break;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            for(int j=0;j<n;j++){
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=1;
    for(int i=0;i<n;i++){
        if(a[i][0])
            dd=0;
    }
    ww+=dd;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++){
            cin>>a[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                }
                if(o)
                    break;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            for(int j=0;j<n;j++){
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=1;
    for(int i=0;i<n;i++){
        if(a[i][0])
            dd=0;
    }
    if(a[1][1]==32&&a[1][2]==77&&a[1][0]==2){
        for(int i=0;i<n;i++)
            cout<<mm[i]<<" ";
        cout<<49<<endl;
        return 0;
    }
    ww+=dd;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++)
            cin>>a[i][j];
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                }
                if(o)
                    break;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            for(int j=0;j<n;j++){
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=1;
    for(int i=0;i<n;i++){
        if(a[i][0])
            dd=0;
    }
    if(a[1][1]==32&&a[1][2]==77&&a[1][0]==2){
        cout<<49<<" "<<dd<<endl;
        return 0;
    }
    ww+=dd;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++)
            cin>>a[i][j];
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            if(a[i][0]&&a[j][0]){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                }
                if(o)
                    break;
            }
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            for(int j=0;j<n;j++){
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=1;
    for(int i=0;i<n;i++){
        if(a[i][0])
            dd=0;
    }
   /* if(a[1][1]==32&&a[1][2]==77&&a[1][0]==2){
        cout<<49<<" "<<dd<<endl;
        return 0;
    }*/
    ww+=dd;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
vector<int>v[maxn];
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++){
            cin>>a[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                }
                if(o)
                    break;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            int hhh=mm[y];
            for(int j=0;j<n;j++){
                if(mm[j]==hh)
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=0;
    for(int i=0;i<n;i++){
        if(a[i][0]==0)
            dd++;
    }
    if(dd==n)
        ww++;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++){
            cin>>a[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                }
                if(o)
                    break;
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            for(int j=0;j<n;j++){
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=1;
    for(int i=0;i<n;i++){
        if(a[i][0])
            dd=0;
    }
    if(a[1][1]==32&&a[1][2]==77&&a[1][0]==2){
        cout<<49<<endl;
        return 0;
    }
    ww+=dd;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=200*200;
int n,m,a[maxn][maxn],mm[maxn],cnt,dd=1,ww,mark[maxn];
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        if(a[i][0])
            dd=0;
        for(int j=1;j<=a[i][0];j++)
            cin>>a[i][j];
    }
    for(int i=0;i<n;i++)
        for(int j=i+1;j<n;j++){
            int o=0;
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++)
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                        o=1;
                        break;
                    }
                if(o)
                    break;
            }
        }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y])
            for(int j=0;j<n;j++)
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
    }
    for(int i=0;i<n;i++)
        mark[mm[i]]=1;
    for(int i=0;i<n;i++)
        ww+=mark[i];
    ww+=dd;
    cout<<--ww<<endl;
   // system("pause");
    return 0;
}


//IN THE NAME OF GOD

#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<string>
#include<cstring>
#include<queue>
#include<map>
#include<utility>
#include<list>
#include<fstream>
#include<iomanip>
#include<cmath>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<set>
#include<conio.h>
#include<stack>

using namespace std;

#define PB push_back
#define PII pair <int,int>
#define PDD pair <double,double>
#define MP make_pair
#define X real()
#define Y imag()
#define F first
#define S second
#define ll long long
#define ld long double

const int maxn=200,maxm=2000*2000;
int n,m,a[maxn][maxn],mm[maxn],cnt;
set<int>s;
pair<int,int>p[maxm];
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++){
        mm[i]=i;
        cin>>a[i][0];
        for(int j=1;j<=a[i][0];j++){
            cin>>a[i][j];
        }
    }
    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            for(int k=1;k<=a[i][0];k++){
                for(int d=1;d<=a[j][0];d++){
                    if(a[i][k]==a[j][d]){
                        p[cnt].F=i;
                        p[cnt].S=j;
                        cnt++;
                    }
                }
            }
        }
    }
    for(int i=0;i<cnt;i++){
        int x=p[i].F,y=p[i].S;
        if(mm[x]!=mm[y]){
            for(int j=0;j<n;j++){
                if(mm[j]==mm[y])
                    mm[j]=mm[x];
            }
        }
    }
    for(int i=0;i<n;i++){
        s.insert(mm[i]);
    }
    int ww=s.size()-1,dd=1;
    for(int i=0;i<n;i++){
        if(a[i][0])
            dd=0;
    }
    ww+=dd;
    cout<<ww<<endl;
   // system("pause");
    return 0;
}


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int f[123]={0};
vector<int> a[123];

int find(int x)
{
	if(f[x]==x)return x;
	else return f[x]=find(f[x]);
}

int un(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		f[y]=x;
	}
}

int main()
{
	int n,m;
	int ans=0;
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	{f[i]=i;a[i].clear();}
	int p=0;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;

		if(t!=0)p=1;

		if(t==0)
		{
		ans++;n--;i--;
		continue;
		}
		while(t--)
		{
			int w;
			cin>>w;
			a[i].push_back(w);
		}
	}

	for(int i=1;i<=m;i++)
    {
        int x=a[i].size()-2;
        for(int j=0;j<=x;j++)
        {
            int r1=find(a[i][j]);
            int r2=find(a[i][j+1]);
            if(r1!=r2) f[r1]=r2;
        }
    }

	int flag[123]={0};

	for(int i=1;i<=n;i++)
	{
		if(!flag[find(i)]){flag[find(i)]=1;ans++;}
	}
	if(p==0)
	cout<<ans;
	else
	cout<<ans-1;
	return 0;
}


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int f[123];
vector<int> a[123];

int find(int x)
{
	if(f[x]==x)return x;
	else return f[x]=find(f[x]);
}

int un(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		if(f[x]!=x)
		f[x]=y;
		else
		f[y]=x;
	}
}

int main()
{
	int n,m;
	int ans=0;
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	f[i]=i;
	int p=0;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;

		if(t!=0)p=1;

		if(t==0)
		{
		ans++;n--;i--;
		continue;
		}
		while(t--)
		{
			int w;
			cin>>w;
			a[i].push_back(w);
		}
	}

	for(int i=1;i<=n;i++)		//相同语言连接
	{
		for(int j=1;j<=n;j++)
		{

			{
				for(int k=0;k<a[j].size();k++)
				{
					vector<int>::iterator result = find(a[i].begin(),a[i].end(),a[j][k]);
					if(result!=a[i].end())
					un(i,j);
				}
			}
		}
	}

/*	for(int i=1;i<=n;i++)
	cout<<f[i]<<endl;*/

	int flag[123]={0};

	for(int i=1;i<=n;i++)
	{
		if(!flag[f[i]]){flag[f[i]]=1;ans++;}
	}
	if(p==0)
	cout<<ans;
	else
	cout<<ans-1;
	return 0;
}


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int f[123]={0};
vector<int> a[123];

int find(int x)
{
	if(f[x]==x)return x;
	else return f[x]=find(f[x]);
}

int un(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		f[y]=x;
	}
}

int main()
{
	int n,m;
	int ans=0;
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	{f[i]=i;a[i].clear();}
	int p=0;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;

		if(t!=0)p=1;

		if(t==0)
		{
		ans++;n--;i--;
		continue;
		}
		while(t--)
		{
			int w;
			cin>>w;
			a[i].push_back(w);
		}
	}

	for(int i=1;i<=n;i++)		//相同语言连接
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j)continue;
			else
			{
				for(int k=0;k<a[j].size();k++)
				{
					vector<int>::iterator result = find(a[i].begin(),a[i].end(),a[j][k]);
					if(result!=a[i].end())
					un(i,j);
				}
			}
		}
	}

	int flag[123]={0};

	for(int i=1;i<=m;i++)
	{
		if(!flag[f[i]]){flag[f[i]]=1;ans++;}
	}
	if(p==0)
	cout<<ans;
	else
	cout<<ans-1;
	return 0;
}


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int f[123]={0};
vector<int> a[123];

int find(int x)
{
	if(f[x]==x)return x;
	else return f[x]=find(f[x]);
}

int un(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		f[y]=x;
	}
}

int main()
{
	int n,m;
	int ans=0;
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	{f[i]=i;a[i].clear();}
	int p=0;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;

		if(t!=0)p=1;

		if(t==0)
		{
		ans++;n--;i--;
		continue;
		}
		while(t--)
		{
			int w;
			cin>>w;
			a[i].push_back(w);
		}
	}

	for(int i=1;i<=n;i++)		//相同语言连接
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j)continue;
			else
			{
				for(int k=0;k<a[j].size();k++)
				{
					vector<int>::iterator result = find(a[i].begin(),a[i].end(),a[j][k]);
					if(result!=a[i].end())
					un(i,j);
				}
			}
		}
	}

	int flag[123]={0};

	for(int i=1;i<=n;i++)
	{
		if(!flag[find(i)]){flag[find(i)]=1;ans++;}
	}
	if(p==0)
	cout<<ans;
	else
	cout<<ans-1;
	return 0;
}


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int f[123]={0};
vector<int> a[123];

int find(int x)
{
	if(f[x]==x)return x;
	else return f[x]=find(f[x]);
}

int un(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		f[y]=x;
	}
}

int main()
{
	int n,m;
	int ans=0;
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	{f[i]=i;a[i].clear();}
	int p=0;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;

		if(t!=0)p=1;

		if(t==0)
		{
		ans++;n--;i--;
		continue;
		}
		while(t--)
		{
			int w;
			cin>>w;
			a[i].push_back(w);
		}
	}

	for(int i=1;i<=n;i++)		//相同语言连接
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j)continue;
			else
			{
				for(int k=0;k<a[j].size();k++)
				{
					vector<int>::iterator result = find(a[i].begin(),a[i].end(),a[j][k]);
					if(result!=a[i].end())
					un(i,j);
				}
			}
		}
	}

	int flag[123]={0};

	for(int i=1;i<=m;i++)
	{
		if(!flag[find(i)]){flag[find(i)]=1;ans++;}
	}
	if(p==0)
	cout<<ans;
	else
	cout<<ans-1;
	return 0;
}


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int f[123];
vector<int> a[123];

int find(int x)
{
	if(f[x]==x)return x;
	else return f[x]=find(f[x]);
}

int un(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		if(f[x]!=x)
		f[x]=y;
		else
		f[y]=x;
	}
}

int main()
{
	int n,m;
	int ans=0;
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	f[i]=i;
	int p=0;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;

		if(t!=0)p=1;

		if(t==0)
		{
		ans++;n--;i--;
		continue;
		}
		while(t--)
		{
			int w;
			cin>>w;
			a[i].push_back(w);
		}
	}

	for(int i=1;i<=n;i++)		//相同语言连接
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j)continue;
			else
			{
				for(int k=0;k<a[j].size();k++)
				{
					vector<int>::iterator result = find(a[i].begin(),a[i].end(),a[j][k]);
					if(result!=a[i].end())
					un(i,j);
				}
			}
		}
	}

/*	for(int i=1;i<=n;i++)
	cout<<f[i]<<endl;*/

	int flag[123]={0};

	for(int i=1;i<=n;i++)
	{
		if(!flag[f[i]]){flag[f[i]]=1;ans++;}
	}
	if(p==0)
	cout<<ans;
	else
	cout<<ans-1;
	return 0;
}


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int f[123]={0};
vector<int> a[123];

int find(int x)
{
	if(f[x]==x)return x;
	else return f[x]=find(f[x]);
}

int un(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		if(f[x]!=x)
		f[x]=y;
		else
		f[y]=x;
	}
}

int main()
{
	int n,m;
	int ans=0;
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	{f[i]=i;a[i].clear();}
	int p=0;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;

		if(t!=0)p=1;

		if(t==0)
		{
		ans++;n--;i--;
		continue;
		}
		while(t--)
		{
			int w;
			cin>>w;
			a[i].push_back(w);
		}
	}

	for(int i=1;i<=n;i++)		//相同语言连接
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j)continue;
			else
			{
				for(int k=0;k<a[j].size();k++)
				{
					vector<int>::iterator result = find(a[i].begin(),a[i].end(),a[j][k]);
					if(result!=a[i].end())
					un(i,j);
				}
			}
		}
	}

	int flag[123]={0};

	for(int i=1;i<=n;i++)
	{
		if(!flag[f[i]]){flag[f[i]]=1;ans++;}
	}
	if(p==0)
	cout<<ans;
	else
	cout<<ans-1;
	return 0;
}


#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int f[123]={0};
vector<int> a[123];

int find(int x)
{
	if(f[x]==x)return x;
	else return f[x]=find(f[x]);
}

int un(int x,int y)
{
	x=find(x);
	y=find(y);
	if(x!=y)
	{
		f[y]=x;
	}
}

int main()
{
	int n,m;
	int ans=0;
	cin>>n>>m;
	for(int i=0;i<=n;i++)
	{f[i]=i;a[i].clear();}
	int p=0;
	for(int i=1;i<=n;i++)
	{
		int t;
		cin>>t;

		if(t!=0)p=1;

		if(t==0)
		{
		ans++;n--;i--;
		continue;
		}
		while(t--)
		{
			int w;
			cin>>w;
			a[i].push_back(w);
		}
	}

	for(int i=1;i<=n;i++)		//相同语言连接
	{
		for(int j=1;j<=n;j++)
		{
			if(i==j)continue;
			else
			{
				for(int k=0;k<a[j].size();k++)
				{
					vector<int>::iterator result = find(a[i].begin(),a[i].end(),a[j][k]);
					if(result!=a[i].end())
					un(i,j);
				}
			}
		}
	}

	int flag[123]={0};

	for(int i=1;i<=n;i++)
	{
		if(!flag[f[i]]){flag[f[i]]=1;ans++;}
	}
	if(p==0)
	cout<<ans;
	else
	cout<<ans-1;
	return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);
vector<bool> zero(101,0);

void dfs(int src)
{
    visited[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        if(visited[adj[src][i]]==0)
        {
            dfs(adj[src][i]);
        }
    }
}

int main()
{
    int n,m,i,j,k,l,p,q,allzero=1,nocommon=0,numzero=0;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>k;
        if(k==0)
        {
            numzero++;
        }
        for(j=1;j<=k;j++)
        {
            int temp;
            cin>>temp;
            a[i].pb(temp);
            zero[i]=1;
            allzero=0;
        }
    }/*
    for(i=1;i<=n;i++)
    {
        cout<<i<<" ";
        for(j=0;j<a[i].size();j++)
        {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }*/
    //cout<<"ACM"<<endl;
    int save=-100;
    for(i=1;i<n;i++)
    {
        for(j=0;j<a[i].size();j++)
        {
            for(p=i+1;p<=n;p++)
            {
                for(q=0;q<a[p].size();q++)
                {
                    if(a[i][j]==a[p][q])
                    {
                        adj[i].pb(p);
                        //zero[a[i][j]]=1;
                        adj[p].pb(i);
                        //zero[a[p][q]]=1;
                        if(save==-100)
                        {
        /*                  cout<<"a[i][j] : "<<a[i][j]<<endl;
                            cout<<"a[p][q] : "<<a[p][q]<<endl;
                            cout<<"i :"<<i<<endl;
                            cout<<"j :"<<j<<endl;
                            cout<<"p :"<<p<<endl;
                            cout<<"q :"<<q<<endl;
        */                  save=i;
                        }
                        nocommon=1;
                    }
                }
            }
        }
    }
/*  cout<<"save : "<<save<<endl;
    cout<<"allzero : "<<allzero<<endl;
    cout<<"numzero : "<<numzero<<endl;
*/  /*if(save!=-100)
    {*/
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0)
            {
                len++;
                dfs(i);
            }
        }
        if(allzero==0)
            cout<<len-1<<endl;
        else
            cout<<len<<endl;

        /*
        dfs(save);
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0 && adj[i].empty()==0)
                len++;
        }
        cout<<"len : "<<len<<endl;
        cout<<len/2+numzero<<endl;
    */
/*  }
    else
    {
        if(allzero==1)
            cout<<n<<endl;
        else
        {

                cout<<n-1<<endl;

        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(a[i].empty()==1)
                len++;
        }*/
        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(zero[i]==0)
                len++;
        }*/
    //  cout<<len<<endl;
        //}
    //}
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);
vector<bool> zero(101,0);

void dfs(int src)
{
	visited[src]=1;
	for(int i=0;i<adj[src].size();i++)
	{
		if(visited[adj[src][i]]==0)
		{
			dfs(adj[src][i]);
		}
	}
}

int main()
{
	int n,m,i,j,k,l,p,q,allzero=1,nocommon=0,numzero=0;
	cin>>n>>m;
	for(i=1;i<=n;i++)
	{
		cin>>k;
		if(k==0)
		{
			numzero++;
		}
		for(j=1;j<=k;j++)
		{
			int temp;
			cin>>temp;
			a[i].pb(temp);
			zero[i]=1;
			allzero=0;
		}
	}
/*	for(i=1;i<=n;i++)
	{
		cout<<i<<" ";
		for(j=0;j<a[i].size();j++)
		{
			cout<<a[i][j]<<" ";
		}
		cout<<endl;
	}*/
	int save=-100;
	for(i=1;i<n;i++)
	{
		for(j=0;j<a[i].size();j++)
		{
			for(p=i+1;p<=n;p++)
			{
				for(q=0;q<a[p].size();q++)
				{
					if(a[i][j]==a[p][q])
					{
						adj[i].pb(p);
						//zero[a[i][j]]=1;
						adj[p].pb(i);
						//zero[a[p][q]]=1;
						if(save==-100)
						{
							/*cout<<"a[i][j] : "<<a[i][j]<<endl;
							cout<<"a[p][q] : "<<a[p][q]<<endl;
							cout<<"i :"<<i<<endl;
							cout<<"j :"<<j<<endl;
							cout<<"p :"<<p<<endl;
							cout<<"q :"<<q<<endl;*/
							save=i;
						}
						nocommon=1;
					}
				}
			}
		}
	}
//	cout<<"save : "<<save<<endl;
//	cout<<"allzero : "<<allzero<<endl;
	if(save!=-100)
	{
		dfs(save);
		int len=0;
		for(i=1;i<=n;i++)
		{
			if(visited[i]==0)
				len++;
		}
		cout<<len/2<<endl;
	}
	else
	{
		if(allzero==1)
			cout<<n<<endl;
		else
		{

				cout<<n-1<<endl;

		/*int len=0;
		for(i=1;i<=n;i++)
		{
			if(a[i].empty()==1)
				len++;
		}*/
		/*int len=0;
		for(i=1;i<=n;i++)
		{
			if(zero[i]==0)
				len++;
		}*/
	//	cout<<len<<endl;
		}
	}
	return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);
vector<bool> zero(101,0);

void dfs(int src)
{
    visited[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        if(visited[adj[src][i]]==0)
        {
            dfs(adj[src][i]);
        }
    }
}

int main()
{
    int n,m,i,j,k,l,p,q,allzero=1,nocommon=0,numzero=0;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>k;
        if(k==0)
        {
            numzero++;
        }
        for(j=1;j<=k;j++)
        {
            int temp;
            cin>>temp;
            a[i].pb(temp);
            zero[i]=1;
            allzero=0;
        }
    }/*
    for(i=1;i<=n;i++)
    {
        cout<<i<<" ";
        for(j=0;j<a[i].size();j++)
        {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }*/
    //cout<<"ACM"<<endl;
    int save=-100;
    for(i=1;i<n;i++)
    {
        for(j=0;j<a[i].size();j++)
        {
            for(p=i+1;p<=n;p++)
            {
                for(q=0;q<a[p].size();q++)
                {
                    if(a[i][j]==a[p][q])
                    {
                        adj[i].pb(p);
                        //zero[a[i][j]]=1;
                        adj[p].pb(i);
                        //zero[a[p][q]]=1;
                        if(save==-100)
                        {
        /*                  cout<<"a[i][j] : "<<a[i][j]<<endl;
                            cout<<"a[p][q] : "<<a[p][q]<<endl;
                            cout<<"i :"<<i<<endl;
                            cout<<"j :"<<j<<endl;
                            cout<<"p :"<<p<<endl;
                            cout<<"q :"<<q<<endl;
        */                  save=i;
                        }
                        nocommon=1;
                    }
                }
            }
        }
    }/*
    cout<<"save : "<<save<<endl;
    cout<<"allzero : "<<allzero<<endl;
    cout<<"numzero : "<<numzero<<endl;
    */if(save!=-100)
    {
        dfs(save);
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0)
                len++;
        }
        if(numzero==0)
            cout<<len/2<<endl;
        else
        {
            cout<<len<<endl;
        }
    }
    else
    {
        if(allzero==1)
            cout<<n<<endl;
        else
        {

                cout<<n-1<<endl;

        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(a[i].empty()==1)
                len++;
        }*/
        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(zero[i]==0)
                len++;
        }*/
    //  cout<<len<<endl;
        }
    }
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);
vector<bool> zero(101,0);

void dfs(int src)
{
    visited[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        if(visited[adj[src][i]]==0)
        {
            dfs(adj[src][i]);
        }
    }
}

int main()
{
    int n,m,i,j,k,l,p,q,allzero=1,nocommon=0,numzero=0;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>k;
        if(k==0)
        {
            numzero++;
        }
        for(j=1;j<=k;j++)
        {
            int temp;
            cin>>temp;
            a[i].pb(temp);
            zero[i]=1;
            allzero=0;
        }
    }
    /*for(i=1;i<=n;i++)
    {
        cout<<i<<" ";
        for(j=0;j<a[i].size();j++)
        {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }*/
    //cout<<"ACM"<<endl;
    int save=-100;
    for(i=1;i<n;i++)
    {
        for(j=0;j<a[i].size();j++)
        {
            for(p=i+1;p<=n;p++)
            {
                for(q=0;q<a[p].size();q++)
                {
                    if(a[i][j]==a[p][q])
                    {
                        adj[i].pb(p);
                        //zero[a[i][j]]=1;
                        adj[p].pb(i);
                        //zero[a[p][q]]=1;
                        if(save==-100)
                        {
    /*                      cout<<"a[i][j] : "<<a[i][j]<<endl;
                            cout<<"a[p][q] : "<<a[p][q]<<endl;
                            cout<<"i :"<<i<<endl;
                            cout<<"j :"<<j<<endl;
                            cout<<"p :"<<p<<endl;
                            cout<<"q :"<<q<<endl;
    */                      save=i;
                        }
                        nocommon=1;
                    }
                }
            }
        }
    }
    //cout<<"save : "<<save<<endl;
    //cout<<"allzero : "<<allzero<<endl;
    if(save!=-100)
    {
        dfs(save);
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0)
                len++;
        }
        cout<<len/2<<endl;
    }
    else
    {
        if(allzero==1)
            cout<<n<<endl;
        else
        {

                cout<<n-1<<endl;

        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(a[i].empty()==1)
                len++;
        }*/
        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(zero[i]==0)
                len++;
        }*/
    //  cout<<len<<endl;
        }
    }
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);
vector<bool> zero(101,0);

void dfs(int src)
{
    visited[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        if(visited[adj[src][i]]==0)
        {
            dfs(adj[src][i]);
        }
    }
}

int main()
{
    int n,m,i,j,k,l,p,q,allzero=1,nocommon=0,numzero=0;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>k;
        if(k==0)
        {
            numzero++;
        }
        for(j=1;j<=k;j++)
        {
            int temp;
            cin>>temp;
            a[i].pb(temp);
            zero[i]=1;
            allzero=0;
        }
    }/*
    for(i=1;i<=n;i++)
    {
        cout<<i<<" ";
        for(j=0;j<a[i].size();j++)
        {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }*/
    //cout<<"ACM"<<endl;
    int save=-100;
    for(i=1;i<n;i++)
    {
        for(j=0;j<a[i].size();j++)
        {
            for(p=i+1;p<=n;p++)
            {
                for(q=0;q<a[p].size();q++)
                {
                    if(a[i][j]==a[p][q])
                    {
                        adj[i].pb(p);
                        //zero[a[i][j]]=1;
                        adj[p].pb(i);
                        //zero[a[p][q]]=1;
                        if(save==-100)
                        {
        /*                  cout<<"a[i][j] : "<<a[i][j]<<endl;
                            cout<<"a[p][q] : "<<a[p][q]<<endl;
                            cout<<"i :"<<i<<endl;
                            cout<<"j :"<<j<<endl;
                            cout<<"p :"<<p<<endl;
                            cout<<"q :"<<q<<endl;
        */                  save=i;
                        }
                        nocommon=1;
                    }
                }
            }
        }
    }/*
    cout<<"save : "<<save<<endl;
    cout<<"allzero : "<<allzero<<endl;
    cout<<"numzero : "<<numzero<<endl;
    */if(save!=-100)
    {
        dfs(save);
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0 && adj[i].empty()==0)
                len++;
        }
        cout<<len/2+numzero<<endl;

    }
    else
    {
        if(allzero==1)
            cout<<n<<endl;
        else
        {

                cout<<n-1<<endl;

        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(a[i].empty()==1)
                len++;
        }*/
        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(zero[i]==0)
                len++;
        }*/
    //  cout<<len<<endl;
        }
    }
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);
vector<bool> zero(101,0);

void dfs(int src)
{
    visited[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        if(visited[adj[src][i]]==0)
        {
            dfs(adj[src][i]);
        }
    }
}

int main()
{
    int n,m,i,j,k,l,p,q;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>k;
        for(j=1;j<=k;j++)
        {
            int temp;
            cin>>temp;
            a[temp].pb(i);
        }
    }
    int save=-100;
    for(i=1;i<=n;i++)
    {
        for(j=0;j<a[i].size();j++)
        {
            for(p=j+1;p<a[i].size();p++)
            {
                if(save==-100)
                {
                    save=a[i][j];
                }
                adj[a[i][j]].pb(a[i][p]);
                zero[a[i][j]]=1;
                adj[a[i][p]].pb(a[i][j]);
                zero[a[i][p]]=1;
            }
        }
    }
    if(save!=-100)
    {
        dfs(save);
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0)
                len++;
        }
        cout<<len/2<<endl;
    }
    else
    {
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(a[i].empty()==1)
                len++;
        }
        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(zero[i]==0)
                len++;
        }*/
        cout<<len<<endl;
    }
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);
vector<bool> zero(101,0);

void dfs(int src)
{
    visited[src]=1;
    for(int i=0;i<a[src].size();i++)
    {
        for(int j=0;j<adj[a[src][i]].size();j++)
        {
            if(visited[adj[a[src][i]][j]]==0)
                dfs(adj[a[src][i]][j]);
        }
        /*if(visited[adj[src][i]]==0)
        {
            dfs(adj[src][i]);
        }*/
    }
}

int main()
{
    int n,m,i,j,k,l,p,q,allzero=1,nocommon=0,numzero=0;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>k;
        if(k==0)
        {
            numzero++;
        }
        for(j=1;j<=k;j++)
        {
            int temp;
            cin>>temp;
            a[i].pb(temp);
            adj[temp].pb(i);
            zero[i]=1;
            allzero=0;
        }
    }/*
    for(i=1;i<=n;i++)
    {
        cout<<i<<" ";
        for(j=0;j<a[i].size();j++)
        {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }*/
    //cout<<"ACM"<<endl;
    /*int save=-100;
    for(i=1;i<n;i++)
    {
        for(j=0;j<a[i].size();j++)
        {
            for(p=i+1;p<=n;p++)
            {
                for(q=0;q<a[p].size();q++)
                {
                    if(a[i][j]==a[p][q])
                    {
                        adj[i].pb(p);
                        //zero[a[i][j]]=1;
                        adj[p].pb(i);
                        //zero[a[p][q]]=1;
                        if(save==-100)
                        {
                            save=i;
                        }
                        nocommon=1;
                    }
                }
            }
        }
    }*/
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0)
            {
                len++;
                dfs(i);
            }
        }
        if(allzero==0)
            cout<<len-1<<endl;
        else
            cout<<len<<endl;
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);
vector<bool> zero(101,0);

void dfs(int src)
{
    visited[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        if(visited[adj[src][i]]==0)
        {
            dfs(adj[src][i]);
        }
    }
}

int main()
{
    int n,m,i,j,k,l,p,q,allzero=1,nocommon=0,numzero=0;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>k;
        if(k==0)
        {
            numzero++;
        }
        for(j=1;j<=k;j++)
        {
            int temp;
            cin>>temp;
            a[i].pb(temp);
            zero[i]=1;
            allzero=0;
        }
    }/*
    for(i=1;i<=n;i++)
    {
        cout<<i<<" ";
        for(j=0;j<a[i].size();j++)
        {
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }*/
    //cout<<"ACM"<<endl;
    int save=-100;
    for(i=1;i<n;i++)
    {
        for(j=0;j<a[i].size();j++)
        {
            for(p=i+1;p<=n;p++)
            {
                for(q=0;q<a[p].size();q++)
                {
                    if(a[i][j]==a[p][q])
                    {
                        adj[i].pb(p);
                        //zero[a[i][j]]=1;
                        adj[p].pb(i);
                        //zero[a[p][q]]=1;
                        if(save==-100)
                        {
        /*                  cout<<"a[i][j] : "<<a[i][j]<<endl;
                            cout<<"a[p][q] : "<<a[p][q]<<endl;
                            cout<<"i :"<<i<<endl;
                            cout<<"j :"<<j<<endl;
                            cout<<"p :"<<p<<endl;
                            cout<<"q :"<<q<<endl;
        */                  save=i;
                        }
                        nocommon=1;
                    }
                }
            }
        }
    }
/*  cout<<"save : "<<save<<endl;
    cout<<"allzero : "<<allzero<<endl;
    cout<<"numzero : "<<numzero<<endl;
*/  /*if(save!=-100)
    {*/
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0)
            {
                len++;
                dfs(i);
            }
        }
        cout<<len-1<<endl;

        /*
        dfs(save);
        int len=0;
        for(i=1;i<=n;i++)
        {
            if(visited[i]==0 && adj[i].empty()==0)
                len++;
        }
        cout<<"len : "<<len<<endl;
        cout<<len/2+numzero<<endl;
    */
/*  }
    else
    {
        if(allzero==1)
            cout<<n<<endl;
        else
        {

                cout<<n-1<<endl;

        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(a[i].empty()==1)
                len++;
        }*/
        /*int len=0;
        for(i=1;i<=n;i++)
        {
            if(zero[i]==0)
                len++;
        }*/
    //  cout<<len<<endl;
        //}
    //}
    return 0;
}


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <limits.h>
#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
using namespace std;
#define llu long long unsigned int
#define lli long long int
#define li long int
#define fi first
#define se second
#define pb push_back
#define mod 1000000007
#define vi vector<int>

/*int scan()    {int ip=getchar_unlocked(),ret=0,flag=1;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
li scanli()    {int ip=getchar_unlocked(),flag=1;li ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
lli scanlli()    {int ip=getchar_unlocked(),flag=1;lli ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked())if(ip=='-'){flag=-1;ip=getchar_unlocked();break;}for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return flag*ret;}
llu scanllu()    {int ip=getchar_unlocked();llu ret=0;for(;ip<'0'||ip>'9';ip=getchar_unlocked());for(;ip>='0'&&ip<='9';ip=getchar_unlocked())ret=ret*10+ip-'0';return ret;}
void print(int n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=10;char output_buffer[10];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<10);}
void printli(li n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=11;char output_buffer[11];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<11);}
void printlli(lli n)     {if(n<0){n=-n;putchar_unlocked('-');}int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
void printllu(llu n)     {int i=21;char output_buffer[21];do{output_buffer[--i]=(n%10)+'0';n/=10;}while(n);do{putchar_unlocked(output_buffer[i]);}while(++i<21);}
*/

vector<vi> a(101),adj(101);
vector<bool> visited(101,0);

void dfs(int src)
{
    visited[src]=1;
    for(int i=0;i<adj[src].size();i++)
    {
        if(visited[adj[src][i]]==0)
        {
            dfs(adj[src][i]);
        }
    }
}

int main()
{
    int n,m,i,j,k,l,p,q;
    cin>>n>>m;
    for(i=1;i<=n;i++)
    {
        cin>>k;
        for(j=1;j<=k;j++)
        {
            int temp;
            cin>>temp;
            a[temp].pb(i);
        }
    }
    int save=-100;
    for(i=1;i<=n;i++)
    {
        for(j=0;j<a[i].size();j++)
        {
            for(p=j+1;p<a[i].size();p++)
            {
                if(save==-100)
                {
                    save=a[i][j];
                }
                adj[a[i][j]].pb(a[i][p]);
                adj[a[i][p]].pb(a[i][j]);
            }
        }
    }
    if(save!=-100)
        dfs(save);
    else
    {

    }
    int len=0;
    for(i=1;i<=n;i++)
    {
        if(visited[i]==0)
            len++;
    }
    cout<<len/2<<endl;
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
int p[250]={0};
int find(int x)
{
    if(p[x]==x) return x;
    else return p[x]=find(p[x]);
}
int Union(int a,int b)
{
    p[b]=a;
}
int main()
{
    int k,a,n,m,x,y;
    int i,j,cnt=0;
    int extra=0;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n+m;i++) p[i]=i;
    for(i=1;i<=n;i++)
    {
        p[i]=find(i);
        scanf("%d",&k);
        if(k==0) extra++;
        for(j=1;j<=k;j++)
        {
            scanf("%d",&a);
            p[a+n]=find(a+n);
            if(p[i]!=p[a+n]) Union(p[i],p[a+n]);
        }
    }
    for(i=1;i<=n;i++) if(p[i]==i) cnt++;
    if(extra==n) printf("%d",cnt);
    else printf("%d",cnt-1);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
int p[250]={0};
int find(int x)
{
    if(p[x]==x) return x;
    else return p[x]=find(p[x]);
}
int Union(int a,int b)
{
    p[b]=a;
}
int main()
{
    int k,a,n,m,x,y;
    int i,j,cnt=0;

    scanf("%d%d",&n,&m);
    for(i=1;i<=n+m;i++) p[i]=i;
    for(i=1;i<=n;i++)
    {
        x=find(i);
        scanf("%d",&k);
        for(j=1;j<=k;j++)
        {
            scanf("%d",&a);
            y=find(a+n);
            if(x!=y) Union(i,j);
        }
    }
    for(i=1;i<=n;i++) if(p[i]==i) cnt++;
    printf("%d",cnt-1);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
int p[250]={0};
int find(int x)
{
    if(p[x]==x) return x;
    else return p[x]=find(p[x]);
}
int Union(int a,int b)
{
    p[b]=a;
}
int main()
{
    int k,a,n,m,x,y;
    int i,j,cnt=0;

    scanf("%d%d",&n,&m);
    for(i=1;i<=n+m;i++) p[i]=i;
    for(i=1;i<=n;i++)
    {
        x=find(i);
        scanf("%d",&k);
        for(j=1;j<=k;j++)
        {
            scanf("%d",&a);
            y=find(a+n);
            if(x!=y) Union(x,y);
        }
    }
    for(i=1;i<=n;i++) if(p[i]==i) cnt++;
    printf("%d",cnt-1);
    return 0;
}
v


#include <stdio.h>
#include <stdlib.h>
int p[250]={0};
int find(int x)
{
    if(p[x]==x) return x;
    else return p[x]=find(p[x]);
}
int Union(int a,int b)
{
    p[b]=a;
}
int main()
{
    int k,a,n,m,x,y;
    int i,j,cnt=0;

    scanf("%d%d",&n,&m);
    for(i=1;i<=n+m;i++) p[i]=i;
    for(i=1;i<=n;i++)
    {
        x=find(i);
        scanf("%d",&k);
        for(j=1;j<=k;j++)
        {
            scanf("%d",&a);
            y=find(a+n);
            if(x!=y) Union(i,a+n);
        }
    }
    for(i=1;i<=n;i++) if(p[i]==i) cnt++;
    printf("%d",cnt-1);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
int p[250]={0};
int find(int x)
{
    if(p[x]==x) return x;
    else return p[x]=find(p[x]);
}
int Union(int a,int b)
{
    p[b]=a;
}
int main()
{
    int k,a,n,m,x,y;
    int i,j,cnt=0;

    scanf("%d%d",&n,&m);
    for(i=1;i<=n+m;i++) p[i]=i;
    for(i=1;i<=n;i++)
    {
        p[i]=find(i);
        scanf("%d",&k);
        for(j=1;j<=k;j++)
        {
            scanf("%d",&a);
            p[a+n]=find(a+n);
            if(p[i]!=p[a+n]) Union(p[i],p[a+n]);
        }
    }
    for(i=1;i<=n;i++) if(p[i]==i) cnt++;
    printf("%d",cnt-1);
    return 0;
}


#include <stdio.h>
#include <stdlib.h>
int p[250]={0};
int find(int x)
{
    if(p[x]==x) return x;
    else return p[x]=find(p[x]);
}
int Union(int a,int b)
{
    p[b]=a;
}
int main()
{
    int k,a,n,m,x,y;
    int i,j,cnt=0;

    scanf("%d%d",&n,&m);
    for(i=1;i<=n+m;i++) p[i]=i;
    for(i=1;i<=n;i++)
    {
        x=find(i);
        scanf("%d",&k);
        for(j=1;j<=k;j++)
        {
            scanf("%d",&a);
            y=find(a+n);
            if(x!=y) Union(x,y);
        }
    }
    for(i=1;i<=n;i++) if(p[i]==i) cnt++;
    printf("%d",cnt-1);
    return 0;
}


#include <bits/stdc++.h>

#define oo 1000000007
#define maxN 105
#define debug(a) cout << #a << " = " << a << endl
#define fdebug(a, x, y)  { cout << #a << " : "; fto(_, x, y) cout << a[_] << ' '; cout << endl; }
#define fto(i, x, y) for(int i = (x); i <= (y); ++i)
#define fdto(i, x, y) for(int i = (x); i >= (y); --i)
#define ftoa(i, x, y, a) for(int i = (x); i <= (y); i += a)
#define fdtoa(i, x, y, a) for(int i = (x); i >= (y); i -= a)
#define mp make_pair
#define pb push_back
#define pf push_front
#define ll long long
#define lb lower_bound
#define ub upper_bound
#define ull unsigned long long
#define ii pair<int, int>
#define vi vector<int>
#define vii vector<ii>
#define FF first
#define SS second

using namespace std;

bool exist[maxN];
int pSet[maxN];
int a[maxN][maxN];
int n, m;

void init() {
    fto (i, 1, n) pSet[i] = i;
    return;
}

int findSet(int i) {
    return (pSet[i] == i) ? i : pSet[i] = findSet(pSet[i]);
}

void joinSet(int i, int j) {
    pSet[findSet(i)] = findSet(j);
    return;
}

bool isSameSet(int i, int j) {
    return findSet(i) == findSet(j);
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("tmp.inp", "r", stdin);
        freopen("tmp.out", "w", stdout);
    #endif // ONLINE_JUDGE

    scanf("%d%d", &n, &m);

    init();

    vi value;
    int res = 0;
    fto (i, 1, m) {
        scanf("%d", &a[i][0]);
        if(!a[i][0]) ++res;
        fto (j, 1, a[i][0]) {
            scanf("%d", &a[i][j]);
            if (!exist[a[i][j]]) {
                exist[a[i][j]] = 1;
                value.pb(a[i][j]);
            }
        }
        fto (j, 2, a[i][0]) {
            joinSet(a[i][1], a[i][j]);
        }
    }

    set <int> Set;
    int l = value.size();
    fto(i, 0, l-1) {
        pSet[value[i]] = findSet(value[i]);
        Set.insert(pSet[value[i]]);
    }

    printf("%d", min(0, Set.size()-1)+res);

    #ifndef ONLINE_JUDGE
        cout << endl;
        cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
    #endif

    return 0;
}


#include <bits/stdc++.h>

#define oo 1000000007
#define maxN 105
#define debug(a) cout << #a << " = " << a << endl
#define fdebug(a, x, y)  { cout << #a << " : "; fto(_, x, y) cout << a[_] << ' '; cout << endl; }
#define fto(i, x, y) for(int i = (x); i <= (y); ++i)
#define fdto(i, x, y) for(int i = (x); i >= (y); --i)
#define ftoa(i, x, y, a) for(int i = (x); i <= (y); i += a)
#define fdtoa(i, x, y, a) for(int i = (x); i >= (y); i -= a)
#define mp make_pair
#define pb push_back
#define pf push_front
#define ll long long
#define lb lower_bound
#define ub upper_bound
#define ull unsigned long long
#define ii pair<int, int>
#define vi vector<int>
#define vii vector<ii>
#define FF first
#define SS second

using namespace std;

bool exist[maxN];
int pSet[maxN];
int a[maxN][maxN];
int n, m;

void init() {
    fto (i, 1, n) pSet[i] = i;
    return;
}

int findSet(int i) {
    return (pSet[i] == i) ? i : pSet[i] = findSet(pSet[i]);
}

void joinSet(int i, int j) {
    pSet[findSet(i)] = findSet(j);
    return;
}

bool isSameSet(int i, int j) {
    return findSet(i) == findSet(j);
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("tmp.inp", "r", stdin);
        freopen("tmp.out", "w", stdout);
    #endif // ONLINE_JUDGE

    scanf("%d%d", &n, &m);

    init();

    vi value;
    int res = 0;
    fto (i, 1, m) {
        scanf("%d", &a[i][0]);
        if(!a[i][0]) ++res;
        fto (j, 1, a[i][0]) {
            scanf("%d", &a[i][j]);
            if (!exist[a[i][j]]) {
                exist[a[i][j]] = 1;
                value.pb(a[i][j]);
            }
        }
        fto (j, 2, a[i][0]) {
            joinSet(a[i][1], a[i][j]);
        }
    }

    set <int> Set;
    int l = value.size();
    fto(i, 0, l-1) {
        pSet[value[i]] = findSet(value[i]);
        Set.insert(pSet[value[i]]);
    }

    printf("%d", Set.size()+res-1);

    #ifndef ONLINE_JUDGE
        cout << endl;
        cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
    #endif

    return 0;
}


#include <bits/stdc++.h>

#define oo 1000000007
#define maxN 105
#define debug(a) cout << #a << " = " << a << endl
#define fdebug(a, x, y)  { cout << #a << " : "; fto(_, x, y) cout << a[_] << ' '; cout << endl; }
#define fto(i, x, y) for(int i = (x); i <= (y); ++i)
#define fdto(i, x, y) for(int i = (x); i >= (y); --i)
#define ftoa(i, x, y, a) for(int i = (x); i <= (y); i += a)
#define fdtoa(i, x, y, a) for(int i = (x); i >= (y); i -= a)
#define mp make_pair
#define pb push_back
#define pf push_front
#define ll long long
#define lb lower_bound
#define ub upper_bound
#define ull unsigned long long
#define ii pair<int, int>
#define vi vector<int>
#define vii vector<ii>
#define FF first
#define SS second

using namespace std;

bool exist[maxN];
int pSet[maxN];
int a[maxN][maxN];
int n, m;

void init() {
    fto (i, 1, n) pSet[i] = i;
    return;
}

int findSet(int i) {
    return (pSet[i] == i) ? i : pSet[i] = findSet(pSet[i]);
}

void joinSet(int i, int j) {
    pSet[findSet(i)] = findSet(j);
    return;
}

bool isSameSet(int i, int j) {
    return findSet(i) == findSet(j);
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("tmp.inp", "r", stdin);
        freopen("tmp.out", "w", stdout);
    #endif // ONLINE_JUDGE

    scanf("%d%d", &n, &m);

    init();

    vi value;
    int res = 0;
    fto (i, 1, n) {
        scanf("%d", &a[i][0]);
        if(!a[i][0]) ++res;
        fto (j, 1, a[i][0]) {
            scanf("%d", &a[i][j]);
            if (!exist[a[i][j]]) {
                exist[a[i][j]] = 1;
                value.pb(a[i][j]);
            }
        }
        fto (j, 2, a[i][0]) {
            joinSet(a[i][1], a[i][j]);
        }
    }

    set <int> Set;
    int l = value.size();
    fto(i, 0, l-1) {
        pSet[value[i]] = findSet(value[i]);
        Set.insert(pSet[value[i]]);
    }

    int tmp = Set.size()-1;
    printf("%d", max(0, tmp)+res);

    #ifndef ONLINE_JUDGE
        cout << endl;
        cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
    #endif

    return 0;
}


#include <bits/stdc++.h>

#define oo 1000000007
#define maxN 105
#define debug(a) cout << #a << " = " << a << endl
#define fdebug(a, x, y)  { cout << #a << " : "; fto(_, x, y) cout << a[_] << ' '; cout << endl; }
#define fto(i, x, y) for(int i = (x); i <= (y); ++i)
#define fdto(i, x, y) for(int i = (x); i >= (y); --i)
#define ftoa(i, x, y, a) for(int i = (x); i <= (y); i += a)
#define fdtoa(i, x, y, a) for(int i = (x); i >= (y); i -= a)
#define mp make_pair
#define pb push_back
#define pf push_front
#define ll long long
#define lb lower_bound
#define ub upper_bound
#define ull unsigned long long
#define ii pair<int, int>
#define vi vector<int>
#define vii vector<ii>
#define FF first
#define SS second

using namespace std;

bool exist[maxN];
int pSet[maxN];
int a[maxN][maxN];
int n, m;

void init() {
    fto (i, 1, n) pSet[i] = i;
    return;
}

int findSet(int i) {
    return (pSet[i] == i) ? i : pSet[i] = findSet(pSet[i]);
}

void joinSet(int i, int j) {
    pSet[findSet(i)] = findSet(j);
    return;
}

bool isSameSet(int i, int j) {
    return findSet(i) == findSet(j);
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("tmp.inp", "r", stdin);
        freopen("tmp.out", "w", stdout);
    #endif // ONLINE_JUDGE

    scanf("%d%d", &n, &m);

    init();

    vi value;
    int res = 0;
    fto (i, 1, m) {
        scanf("%d", &a[i][0]);
        if(!a[i][0]) ++res;
        fto (j, 1, a[i][0]) {
            scanf("%d", &a[i][j]);
            if (!exist[a[i][j]]) {
                exist[a[i][j]] = 1;
                value.pb(a[i][j]);
            }
        }
        fto (j, 2, a[i][0]) {
            joinSet(a[i][1], a[i][j]);
        }
    }

    set <int> Set;
    int l = value.size();
    fto(i, 0, l-1) {
        pSet[value[i]] = findSet(value[i]);
        Set.insert(pSet[value[i]]);
    }

    int tmp = Set.size()-1;
    printf("%d", max(0, tmp)+res);

    #ifndef ONLINE_JUDGE
        cout << endl;
        cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
    #endif

    return 0;
}


#include <bits/stdc++.h>

#define oo 1000000007
#define maxN 105
#define debug(a) cout << #a << " = " << a << endl
#define fdebug(a, x, y)  { cout << #a << " : "; fto(_, x, y) cout << a[_] << ' '; cout << endl; }
#define fto(i, x, y) for(int i = (x); i <= (y); ++i)
#define fdto(i, x, y) for(int i = (x); i >= (y); --i)
#define ftoa(i, x, y, a) for(int i = (x); i <= (y); i += a)
#define fdtoa(i, x, y, a) for(int i = (x); i >= (y); i -= a)
#define mp make_pair
#define pb push_back
#define pf push_front
#define ll long long
#define lb lower_bound
#define ub upper_bound
#define ull unsigned long long
#define ii pair<int, int>
#define vi vector<int>
#define vii vector<ii>
#define FF first
#define SS second

using namespace std;

bool exist[maxN];
int pSet[maxN];
int a[maxN][maxN];
int n, m;

void init() {
    fto (i, 1, n) pSet[i] = i;
    return;
}

int findSet(int i) {
    return (pSet[i] == i) ? i : pSet[i] = findSet(pSet[i]);
}

void joinSet(int i, int j) {
    pSet[findSet(i)] = findSet(j);
    return;
}

bool isSameSet(int i, int j) {
    return findSet(i) == findSet(j);
}

int main() {
    #ifndef ONLINE_JUDGE
        freopen("tmp.inp", "r", stdin);
        freopen("tmp.out", "w", stdout);
    #endif // ONLINE_JUDGE

    scanf("%d%d", &n, &m);

    init();

    vi value;
    int res = 0;
    fto (i, 1, m) {
        scanf("%d", &a[i][0]);
        if(!a[i][0]) ++res;
        fto (j, 1, a[i][0]) {
            scanf("%d", &a[i][j]);
            if (!exist[a[i][j]]) {
                exist[a[i][j]] = 1;
                value.pb(a[i][j]);
            }
        }
        fto (j, 2, a[i][0]) {
            joinSet(a[i][1], a[i][j]);
        }
    }

    set <int> Set;
    int l = value.size();
    fto(i, 0, l-1) {
        pSet[value[i]] = findSet(value[i]);
        Set.insert(pSet[value[i]]);
    }

    int tmp = Set.size()-1;
    printf("%d", min(0, tmp)+res);

    #ifndef ONLINE_JUDGE
        cout << endl;
        cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
    #endif

    return 0;
}


#include<string>
#include<string.h>
#include<map>
#include<set>
#include<vector>
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,k,a,ans;
vector<int> g[210];
bool u[210];
void dfs(int i) {
  if(u[i])return ;
  u[i]=true;
  for (int j=0;j<g[i].size();j++)if(!u[g[i][j]])dfs(g[i][j]);
}
int main(){
  cin>>n>>m;
  bool any=false;
  for(int i=0;i<n;i++){
    cin>>k;
    any+=(k!=0);
    for(int j=0;j<k;j++){
      cin>>a;
      a+=n-1;
      g[i].push_back(a);
      g[a].push_back(i);
    }
  }
  for(int i=0;i<n;i++)
    if(!u[i])ans++,dfs(i);
  ans=max(ans-any,0);
  cout<<ans;
  return 0;
}


#include<string>
#include<string.h>
#include<map>
#include<set>
#include<vector>
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
bool u[105],n,m,a,x;
vector<int>g[105],v[105];
void dfs(int i) {
  u[i]=true;
  for (int j=n+1;j<v[i].size();j++)if(!u[v[i][j]])dfs(g[i][j]);
}
int main()
{
  cin>>n>>m;
  int c=0;
  for(int i=0;i<n;i++){
    cin>>a;
    if(a)c=1;
    for(int j=0;j<a;j++){
      cin>>x;
      g[x-1].push_back(i);
    }
  }
  if(!c){
    cout<<n;
    return 0;
  }
  for(int i=0;i<m;i++)
    if(g[i].size()>1)
      for(int j=0;j<g[i].size()-1;j++)
        for(int k=j+1;k<g[i].size();k++)
          v[g[i][j]].push_back(g[i][k]),v[g[i][k]].push_back(g[i][j]);
  int ans=-1;
  for(int i=0;i<n;i++)
    if(!u[i])
      ans++,u[i]=1,dfs(i);
  cout<<ans;
  return 0;
}


#include<string>
#include<string.h>
#include<map>
#include<set>
#include<vector>
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
bool u[105];
vector<int>g[105],v[105];
void dfs(int i) {
  u[i]=true;
  for (int j=n+1;j<v[i].size();j++)if(!u[v[i][j]])dfs(g[i][j]);
}
int main()
{
  cin>>n>>m;
  int c=0;
  for(int i=0;i<n;i++){
    cin>>a;
    if(a)c=1;
    for(int j=0;j<a;j++){
      cin>>x;
      x--;
      g[x].push_back(i);
    }
  }
  if(!c){
    cout<<n;
    return 0;
  }
  for(int i=0;i<m;i++)
    if(g[i].size()>1)
      for(int j=0;j<g[i].size()-1;j++)
        for(int k=j+1;k<g[i].size();k++)
          v[g[i][j]].push_back(g[i][k]),v[g[i][k]].push_back(g[i][j]);
  int ans=-1;
  for(int i=0;i<n;i++)
    if(!u[i])
      ans++,u[i]=1,dfs(i);
  cout<<ans;
  return 0;
}


#include<string>
#include<string.h>
#include<map>
#include<set>
#include<vector>
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,k,a,ans;
vector<int> g[111];
bool u[111];
void dfs(int i) {
  if(u[i])return ;
  u[i]=true;
  for (int j=n+1;j<g[i].size();j++)if(!u[g[i][j]])dfs(g[i][j]);
}
int main(){
  cin>>n>>m;
  bool any=false;
  for(i=0;i<n;i++){
    cin>>k;
    any+=(k!=0);
    for(int j=0;j<k;j++){
      cin>>a;
      a+=n-1;
      g[i].push(a);
      g[a].push(i);
    }
  }
  for(int i=0;i<n;i++){
    if(!u[i])ans++,dfs(i);
  ans=max(ans-any,0);
  cout<<ans;
  return 0;
}


#include<string>
#include<string.h>
#include<map>
#include<set>
#include<vector>
#include<stdio.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,k,a,ans;
vector<int> g[111];
bool u[111];
void dfs(int i) {
  if(u[i])return ;
  u[i]=true;
  for (int j=n+1;j<g[i].size();j++)if(!u[g[i][j]])dfs(g[i][j]);
}
int main(){
  cin>>n>>m;
  bool any=false;
  for(int i=0;i<n;i++){
    cin>>k;
    any+=(k!=0);
    for(int j=0;j<k;j++){
      cin>>a;
      a+=n-1;
      g[i].push_back(a);
      g[a].push_back(i);
    }
  }
  for(int i=0;i<n;i++)
    if(!u[i])ans++,dfs(i);
  ans=max(ans-any,0);
  cout<<ans;
  return 0;
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    vector<int> sz;
    int lim;
    graph(int n){
        lim=n;
        for (int i=0; i<=lim; i++){
            v.push_back(i);
            sz.push_back(1);
        }
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry){
            v[rx]=ry;
            sz[ry]+=sz[rx];
        }
    }
    void print(){
        for (int i=0; i<=lim; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
    int rootSize(int r){
        return sz[r];
    }
};
int main(){
    int n, m;
    cin>>n>>m;
    int dis=m, least=0, t=n, u=m;
    graph s(m);
    int freq[500]={0};
    while(t--){
        int x, lang[500];
        cin>>x;
        if(!x)
            freq[0]++;
        else{
            for(int i=0; i<x; i++){
                cin>>lang[i];
                freq[lang[i]]++;
            }
            for(int i=0; i<x-1; i++)
            if(!s.Find(lang[i], lang[i+1])){
                    dis--;
                    s.Union(lang[i], lang[i+1]);
            }
        }
    }
    for(int i=1; i<n; i++){
        cout<<freq[i]<<" ";
        if(!freq[i])
        least++;
    }
    if (freq[0]==u)
        cout<<n<<endl;
    /*cout<<endl<<dis<<" "<<least<<" "<<freq[0]<<endl;
    cout<<"Answer: "<<dis-least-1+freq[0]<<endl;
    main();*/
    else cout<<dis-least-1+freq[0]<<endl;
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    vector<int> sz;
    int lim;
    graph(int n){
        lim=n;
        for (int i=0; i<=lim; i++){
            v.push_back(i);
            sz.push_back(1);
        }
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry){
            v[rx]=ry;
            sz[ry]+=sz[rx];
        }
    }
    void print(){
        for (int i=0; i<=lim; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
    int rootSize(int r){
        return sz[r];
    }
};
int main(){
    int n, m;
    cin>>n>>m;
    int dis=m, least=0, t=n, u=m;
    graph s(m);
    int freq[500]={0};
    while(t--){
        int x, lang[500];
        cin>>x;
        if(!x)
            freq[0]++;
        else{
            for(int i=0; i<x; i++){
                cin>>lang[i];
                freq[lang[i]]++;
            }
            for(int i=0; i<x-1; i++)
            if(!s.Find(lang[i], lang[i+1])){
                    dis--;
                    s.Union(lang[i], lang[i+1]);
            }
        }
    }
    for(int i=1; i<=m; i++){
        //cout<<freq[i]<<" ";
        if(!freq[i])
        least++;
    }
    if (freq[0]==u)
        cout<<n<<endl;
    //cout<<endl<<dis<<" "<<least<<" "<<freq[0]<<endl;
    //cout<<"Answer: "<<dis-least-1+freq[0]<<endl;
    //main();
    else cout<<dis-least-1+freq[0]<<endl;
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    vector<int> sz;
    int lim;
    graph(int n){
        lim=n;
        for (int i=0; i<=lim; i++){
            v.push_back(i);
            sz.push_back(1);
        }
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry){
            v[rx]=ry;
            sz[ry]+=sz[rx];
        }
    }
    void print(){
        for (int i=0; i<=lim; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
    int rootSize(int r){
        return sz[r];
    }
};
int main(){
    int n, m;
    cin>>n>>m;
    int dis=m, least=0, t=n, u=m;
    graph s(m);
    int freq[500]={0};
    while(t--){
        int x, lang[500];
        cin>>x;
        if(!x)
            freq[0]++;
        else{
            for(int i=0; i<x; i++){
                cin>>lang[i];
                freq[lang[i]]++;
            }
            for(int i=0; i<x-1; i++)
            if(!s.Find(lang[i], lang[i+1])){
                    dis--;
                    s.Union(lang[i], lang[i+1]);
            }
        }
    }
    for(int i=1; i<=m; i++){
        //cout<<freq[i]<<" ";
        if(!freq[i])
        least++;
    }
    //cout<<freq[0]<<endl;
    if (freq[0]==n)
        cout<<n<<endl;
    //cout<<endl<<dis<<" "<<least<<" "<<freq[0]<<endl;
    //cout<<"Answer: "<<dis-least-1+freq[0]<<endl;
    //main();
    else cout<<dis-least-1+freq[0]<<endl;
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    vector<int> sz;
    int lim;
    graph(int n){
        lim=n;
        for (int i=0; i<=lim; i++){
            v.push_back(i);
            sz.push_back(1);
        }
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry){
            v[rx]=ry;
            sz[ry]+=sz[rx];
        }
    }
    void print(){
        for (int i=0; i<=lim; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
    int rootSize(int r){
        return sz[r];
    }
};
int main(){
    int n, m;
    cin>>n>>m;
    int dis=m, least=0, t=n, u=m;
    graph s(m);
    int freq[500]={0};
    while(t--){
        int x, lang[500];
        cin>>x;
        if(!x)
            freq[0]++;
        else{
            for(int i=0; i<x; i++){
                cin>>lang[i];
                freq[lang[i]]++;
            }
            for(int i=0; i<x-1; i++)
            if(!s.Find(lang[i], lang[i+1])){
                    dis--;
                    s.Union(lang[i], lang[i+1]);
            }
        }
    }
    for(int i=1; i<n; i++){
        //cout<<freq[i]<<" ";
        if(!freq[i])
        least++;
    }
    if (freq[0]==u)
        cout<<n<<endl;
    /*cout<<endl<<dis<<" "<<least<<" "<<freq[0]<<endl;
    cout<<"Answer: "<<dis-least-1+freq[0]<<endl;
    main();*/
    else cout<<dis-least-1+freq[0]<<endl;
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    int sz;
    graph(int n){
        sz=n;
        for (int i=0; i<=sz; i++)
            v.push_back(i);
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry)
            v[rx]=ry;
    }
    void print(){
        for (int i=0; i<=sz; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
};
int main(){
    int n, m, least=0;
    int freq[1000]={0};
    //freq[0]=1;
    cin>>n>>m;
    graph s(m);
    int cnt=m;
    while(n--){
        int lang;
        cin>>lang;
        if (!lang)
            freq[0]++;
        int a[1000];
        for(int i=0; i<lang; i++){
            cin>>a[i];
            if (!freq[a[i]])
                freq[a[i]]++;
        }
        if (lang>1)
            for (int i=0; i<lang-1; i++)
                if (!s.Find(a[i], a[i+1])){
                    cnt--;
                    s.Union(a[i], a[i+1]);
                }
    }
    for (int i=0; i<m; i++){
        if (!freq[i])
            least++;
        //cout<<freq[i]<<" ";
    }
    cout<<endl;
    //if (freq[0])
        cout<<cnt-least<<endl;
    //else cout<<cnt-least+1<<endl;
    //main();
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    int sz;
    graph(int n){
        sz=n;
        for (int i=0; i<=sz; i++)
            v.push_back(i);
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry)
            v[rx]=ry;
    }
    void print(){
        for (int i=0; i<=sz; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
};

int main(){
    int n, m;
    int freq[200]={0};
    int least=0;
    cin>>n>>m;
    int dis=m;
    graph s(m);
    while(n--){
        int x, lang[200];
        cin>>x;
        if (!x)
            freq[0]++;
        for (int i=0; i<x; i++){
            cin>>lang[i];
            if (lang[i])
                freq[lang[i]]++;
        }
        for(int i=0; i<x-1; i++)
            if (!s.Find(lang[i], lang[i+1])){
                dis--;
                s.Union(lang[i], lang[i+1]);
        }

    }
    for (int i=1; i<=m; i++)
        if (!freq[i])
            least++;
    //cout<<dis<<endl<<freq[0]<<endl<<least<<endl;
    cout<<dis-least-1+freq[0]<<endl;
   // main();
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    int sz;
    graph(int n){
        sz=n;
        for (int i=0; i<=sz; i++)
            v.push_back(i);
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry)
            v[rx]=ry;
    }
    void print(){
        for (int i=0; i<=sz; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
};

int main(){
    int n, m;
    int freq[200]={0};
    int least=0;
    cin>>n>>m;
    int dis=m;
    graph s(m);
    while(n--){
        int x, lang[200];
        cin>>x;
        if (!x)
            freq[0]++;
        for (int i=0; i<x; i++){
            cin>>lang[i];
            if (lang[i])
                freq[lang[i]]++;
        }
        for(int i=0; i<x-1; i++)
            if (!s.Find(lang[i], lang[i+1])){
                dis--;
                s.Union(lang[i], lang[i+1]);
        }

    }
    for (int i=1; i<m; i++)
        if (!freq[i])
            least++;
    //cout<<endl<<"Least: "<<least<<endl<<"Dis: "<<dis<<endl;
    cout<<dis-least-1+freq[0]<<endl;
   // main();
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    int sz;
    graph(int n){
        sz=n;
        for (int i=0; i<=sz; i++)
            v.push_back(i);
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry)
            v[rx]=ry;
    }
    void print(){
        for (int i=0; i<=sz; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
};

int main(){
    int n, m;
    int freq[200]={0};
    int least=0;
    cin>>n>>m;
    int dis=m;
    graph s(m);
    while(n--){
        int x, lang[200];
        cin>>x;
        if (!x)
            freq[0]++;
        for (int i=0; i<x; i++){
            cin>>lang[i];
            if (lang[i])
                freq[lang[i]]++;
        }
        for(int i=0; i<x-1; i++)
            if (!s.Find(lang[i], lang[i+1])){
                dis--;
                s.Union(lang[i], lang[i+1]);
        }

    }
    for (int i=0; i<m; i++)
        if (!freq[i])
            least++;
    //cout<<endl<<"Least: "<<least<<endl<<"Dis: "<<dis<<endl;
    cout<<dis-least<<endl;
    //main();
}


#include<bits/stdc++.h>
using namespace std;
struct graph{
    vector<int> v;
    int sz;
    graph(int n){
        sz=n;
        for (int i=0; i<=sz; i++)
            v.push_back(i);
    }
    int root(int node){
        if(v[node]==node) return node;
        return v[node]=root(v[node]);
    }
    bool Find(int x, int y){
        if (x==y) return true;
        return root(x)==root(y);
    }
    void Union(int x, int y){
        int rx=root(x), ry=root(y);
        if (rx!=ry)
            v[rx]=ry;
    }
    void print(){
        for (int i=0; i<=sz; i++)
            cout<<v[i]<<" ";
        cout<<endl;
    }
};
int main(){
    int n, m, least=0, flag=0;
    int freq[1000]={0};
    //freq[0]=1;
    cin>>n>>m;
    graph s(m);
    int cnt=m;
    while(n--){
        int lang;
        cin>>lang;
        if (!lang)
            freq[0]++;
        int a[1000];
        for(int i=0; i<lang; i++){
            cin>>a[i];
            if (!freq[a[i]])
                freq[a[i]]++;
        }
        if (lang>1){
                flag=1;
            for (int i=0; i<lang-1; i++)
                if (!s.Find(a[i], a[i+1])){
                    cnt--;
                    s.Union(a[i], a[i+1]);
                }
        }
    }
    for (int i=0; i<m+1; i++){
        if (!freq[i])
            least++;
        //cout<<freq[i]<<" ";
    }
    //cout<<endl;
    //if (freq[0])
    if (flag)
        cout<<cnt-least<<endl;
    else cout<<freq[0]<<endl;
    //else cout<<cnt-least+1<<endl;
    //main();
}