#define _CRT_SECURE_NO_WARNINGS #define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING #include using namespace std; #define CRP(t, x) const t &x #define OPL(t, x) bool operator<(CRP(t, x)) const #define FIL(x, v) memset(x, v, sizeof(x)) #define CLR(x) FIL(x, 0) #define NE1(x) FIL(x, -1) #define INF(x) FIL(x, 0x3f) #ifndef _DEBUG #define _DEBUG 0 #endif // !_DEBUG #define IFD if (_DEBUG) typedef long long ll, i64; inline void read(int &x) { int ch = x = 0; while (!isdigit(ch = getchar())) ; for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0'; } const int N = 505 * 505, inf = 0x3f3f3f3f; int adj[N], nxt[N << 1], to[N << 1], cap[N << 1], cur[N], cnt[N], dis2[N], fa[N], ecnt; inline void addEdge_impl_(int f, int t, int c) { nxt[ecnt] = adj[f]; adj[f] = ecnt; to[ecnt] = t; cap[ecnt] = c; ecnt++; } inline void addEdge(int f, int t, int c) { addEdge_impl_(f, t, c); addEdge_impl_(t, f, 0); } int ISAP(int S, int T) { int flow = 0; for (int i = 0; i < N; i++) dis2[i] = N - 1; int len = 0, x; static int que[N]; dis2[que[len++] = T] = 0; for (int i = 0; i < len; i++) for (int e = adj[x = que[i]]; ~e; e = nxt[e]) if (cap[e ^ 1] && dis2[to[e]] > dis2[x] + 1) dis2[que[len++] = to[e]] = dis2[x] + 1; memset(cnt, 0, sizeof(cnt)); for (int i = 0; i < N; i++) cur[i] = adj[i], cnt[dis2[i]]++; x = S; while (dis2[S] < N - 1) { if (x == T) { int curFlow = inf; for (x = T; x != S; x = to[fa[x] ^ 1]) curFlow = min(curFlow, cap[fa[x]]); for (x = T; x != S; x = to[fa[x] ^ 1]) cap[fa[x]] -= curFlow, cap[fa[x] ^ 1] += curFlow; flow += curFlow, x = S; } bool needRetreat = true; for (int e = cur[x]; needRetreat && ~e; e = nxt[e]) if (cur[x] = e, cap[e] && dis2[x] == dis2[to[e]] + 1) needRetreat = false, fa[x = to[e]] = e; if (needRetreat) { int nd = N - 2; for (int e = adj[x]; ~e; e = nxt[e]) if (cap[e]) nd = min(nd, dis2[to[e]]); if (--cnt[dis2[x]] == 0) break; ++cnt[dis2[x] = nd + 1]; cur[x] = adj[x]; if (x != S) x = to[fa[x] ^ 1]; } } return flow; } int sm[N]; int main() { int n, m, k; read(n), read(m), read(k); NE1(adj), ecnt = 0; addEdge(0, n + m + 1, k); for (int i = 1, cnt; i <= n; i++) { read(cnt), addEdge(0, i, 1), addEdge(n + m + 1, i, 1); for (int j = 0, x; j < cnt; j++) read(x), addEdge(i, n + x, 1); } for (int i = 1; i <= m; i++) addEdge(n + i, n + m + 2, 1); printf("%d\n", ISAP(0, n + m + 2)); return 0; }