#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int st[1001], t[1001];
int map[1001][1001], level[1001]; //使用邻接矩阵来存边,方便读取
bool station[1001], cut[1001]; //判断本站有无火车停靠;是否已经删除这个点
int main() {
int n, m;
cin >> n >> m;
for (int i = 1; i <= m; i++) {
memset(station, false, sizeof(station)); //一开始没有任何火车停靠
int s;
cin >> s;
for (int j = 1; j <= s; j++) {
cin >> st[j];
station[st[j]] = true; // 表示本站有火车停靠
}
for (int j = st[1]; j <= st[s]; j++) { //枚举每个站点
if (station[j] == false) { //没有火车停靠本站点
for (int k = 1; k <= s; k++) {
if (map[j][st[k]] == 0) {
map[j][st[k]] = 1; //连边
level[st[k]]++;
}
}
}
}
}
memset(cut, false, sizeof(cut));
int ans = 0, top = 0;
do {
top = 0;
for (int i = 1; i <= n; i++) {
if (level[i] == 0 && cut[i] == false) { //这个车站的级别为 0 且没有删去这个点
cut[i] = true;
top++;
t[top] = i;
}
}
for (int i = 1; i <= top; i++) {
for (int j = 1; j <= n; j++) {
if (map[t[i]][j] == 1) {
map[t[i]][j] = 0;
level[j]--;
}
}
}
ans++;
} while(top != 0);
cout << ans - 1 << endl; // ans 会多加一次
return 0;
}