采用拓扑排序,
#include <iostream>
#include <queue>
using namespace std;
static int head[10001], nxt[10001], to[10001], stop[1001];
static int indegree[10001], ans[10001], cnt = 1;
static void add_edge(int u, int v)
{
nxt[cnt] = head[u];
to[cnt] = v;
head[u] = cnt++;
}
static void topu(int n)
{
queue<int> buf;
for (int i = 1; i <= n; ++i)
if (!indegree[i]) buf.emplace(i),ans[i] = 1;
while (!buf.empty())
{
auto fr = buf.front();
buf.pop();
for (int ei = head[fr]; ei; ei = nxt[ei])
{
auto dest = to[ei];
ans[dest] = max(ans[dest], ans[fr] + 1);
indegree[dest]--;
if (!indegree[dest]) buf.emplace(dest);
}
}
}
int main()
{
int n, m;
cin >> n >> m;
for (int i = 0; i < m; ++i)
{
int num;
cin >> num;
memset(stop, false, sizeof stop);
for (int c = 1; c <= num; ++c)
{
int d;
cin >> d;
stop[d] = true;
}
vector<int> ust, st;
for (int i = 1; i <= num; ++i)
{
if (!stop[i]) ust.emplace_back(i);
else st.emplace_back(i);
}
for (auto u : ust)
for (auto v : st)
add_edge(u, v), indegree[v]++;
}
topu(n);
int maxn = 1;
for (int i = 1; i <= n; ++i)
maxn = max(maxn, ans[i]);
cout << maxn << endl;
}