Problem:
Problem G:
Make Friendships
Isaac H. Ives attended an international student party and made a lot of girl friends (as many other persons
expected). To strike up a good friendship with them, he decided to have dates with them. However, it
is hard for him to schedule dates because he made so many friends. Thus he decided to find the best
schedule using a computer program. The most important criterion in scheduling is how many different
girl friends he will date. Of course, the more friends he will date, the better the schedule is. However,
though he has the ability to write a program finding the best schedule, he doesn’t have enough time to
write it.
Your task is to write a program to find the best schedule instead of him.
Input
The input consists of a series of data sets. The first line of each data set contains a single positive integer
N
(
N
≤ 1,000) that represents the number of persons Isaac made friends with in the party. The next line
gives Isaac’s schedule, followed by
N
lines that give his new friends’ schedules. Each schedule consists of
a positive integer
M
that represents the number of available days followed by
M
positive integers each
of which represents an available day.
The input is terminated by a line that contains a single zero. This is not part of data sets and should
not be processed.
Output
For each data set, print a line that contains the maximum number of girl friends Isaac can have dates
with.
Sample Input
3
3 1 3 5
2 1 4
4 1 2 3 6
1 3
0
Output for the Sample Input
2

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<pair<ll ,ll>>> vvpll;
typedef vector<vector<ll>> vvll;
typedef vector<vector<vector<ll>>> vvvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
typedef tuple<ll , ll , ll , ll> tpl4;
typedef tuple<ll , ll , ll , ll , ll> tpl5;
typedef tuple<ll , ll , ll , ll , ll , ll> tpl6;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}}
ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

struct Edge {
 ll to,cap,rev;
};

class MaximumFlow{
  public:
  ll siz = 0;
  vector<bool> used;
  vector<vector<Edge>> G;
  MaximumFlow(ll n){
    siz = n;
    used.resize(n+1);
    G.resize(n+1);
  }

  // a からbにcリットル流せる辺を追加
  void add_edge(ll a,ll b , ll c){
    ll ga_size = G[a].size();
    ll gb_size = G[b].size();
    G[a].push_back({b,c,gb_size });
    G[b].push_back({a,0,ga_size });
  }

  //Fはスタートからposまでの残余グラフの辺の容量の最小値
  //返り値は流したフローの量
  ll dfs(ll pos,ll goal,ll F){
    // ゴールに到着
    if(pos == goal) return F;
    used[pos] = true;
    for(ll i = 0; i < (ll)G[pos].size();i++){
      // 容量0の辺は使えない
      if(G[pos][i].cap == 0)continue;
      //探索済みだった
      if(used[G[pos][i].to] ==  true) continue;

      ll flow = dfs(G[pos][i].to,goal,min(F,G[pos][i].cap));

      // フローを流せるとき、残余グラフの容量をflowだけ増減
      if(flow > 0){
        G[pos][i].cap -= flow;
        G[G[pos][i].to][G[pos][i].rev].cap += flow;
        return flow;
      }
    }
    // 見つからず
    return 0;
  }

  ll max_flow(ll s,ll t){
    ll Total_Flow = 0;
    while(true){
      for(ll i = 0;i < siz;i++)used[i] = false;
      ll F = dfs(s,t,INF);

      //流せなくなった
      if(F== 0)break;
      Total_Flow += F;
    }
    return Total_Flow;
  }
};
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while(true){
    LL(n);
    if(n == 0)break;
    LL(m);
    map<ll,ll> mp;
    rep(i,m){
      LL(u);
      ll siz = sz(mp);
      if(!mp.contains(u)){
        mp[u] = siz;
      }
    }
    MaximumFlow mf(n+m+2);
    rep(i,m){
      mf.add_edge(n+m,i,1);
    }
    rep(i,n){
      LL(x);
      rep(j,x){
        LL(v);
        if(mp.contains(v)){
          mf.add_edge(mp[v],i+m,1);
        }
      }
      mf.add_edge(i+m,n+m+1,1);
    }
    cout << mf.max_flow(n+m,n+m+1) << endl;
  }
}
accuracy: 1
time_ms: 30
memory_kb: 4096
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<pair<ll ,ll>>> vvpll;
typedef vector<vector<ll>> vvll;
typedef vector<vector<vector<ll>>> vvvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
typedef tuple<ll , ll , ll , ll> tpl4;
typedef tuple<ll , ll , ll , ll , ll> tpl5;
typedef tuple<ll , ll , ll , ll , ll , ll> tpl6;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}}
ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

struct Edge {
 ll to,cap,rev;
};

class MaximumFlow{
  public:
  ll siz = 0;
  vector<bool> used;
  vector<vector<Edge>> G;
  MaximumFlow(ll n){
    siz = n;
    used.resize(n+1);
    G.resize(n+1);
  }

  // a からbにcリットル流せる辺を追加
  void add_edge(ll a,ll b , ll c){
    ll ga_size = G[a].size();
    ll gb_size = G[b].size();
    G[a].push_back({b,c,gb_size });
    G[b].push_back({a,0,ga_size });
  }

  //Fはスタートからposまでの残余グラフの辺の容量の最小値
  //返り値は流したフローの量
  ll dfs(ll pos,ll goal,ll F){
    // ゴールに到着
    if(pos == goal) return F;
    used[pos] = true;
    for(ll i = 0; i < (ll)G[pos].size();i++){
      // 容量0の辺は使えない
      if(G[pos][i].cap == 0)continue;
      //探索済みだった
      if(used[G[pos][i].to] ==  true) continue;

      ll flow = dfs(G[pos][i].to,goal,min(F,G[pos][i].cap));

      // フローを流せるとき、残余グラフの容量をflowだけ増減
      if(flow > 0){
        G[pos][i].cap -= flow;
        G[G[pos][i].to][G[pos][i].rev].cap += flow;
        return flow;
      }
    }
    // 見つからず
    return 0;
  }

  ll max_flow(ll s,ll t){
    ll Total_Flow = 0;
    while(true){
      for(ll i = 0;i < siz;i++)used[i] = false;
      ll F = dfs(s,t,INF);

      //流せなくなった
      if(F== 0)break;
      Total_Flow += F;
    }
    return Total_Flow;
  }
};
 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while(true){
    LL(n);
    if(n == 0)break;
    LL(m);
    map<ll,ll> mp;
    rep(i,m){
      LL(u);
      ll siz = sz(mp);
      mp[u];
    }
    ll idx = 0;
    for (auto& elem : mp) elem.second = idx++;
    MaximumFlow mf(n+m+2);
    rep(i,m){
      mf.add_edge(n+m,i,1);
    }
    rep(i,n){
      LL(x);
      rep(j,x){
        LL(v);
        if(mp.contains(v)){
          mf.add_edge(mp[v],i+m,1);
        }
      }
      mf.add_edge(i+m,n+m+1,1);
    }
    cout << mf.max_flow(n+m,n+m+1) << endl;
  }
}
accuracy: 1
time_ms: 30
memory_kb: 4096
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <queue>
#include <set>
using namespace std;
typedef long long ll;
#define rep(i, n) for(int i = 0; i < (n); i++)

template<class T>
using vi = vector<T>;

template<class T>
using vii = vector<vi<T>>;

template<class T>
using viii = vector<vii<T>>;

struct Dinic {
private:
    const long long inf = 1e18;
    vector<int> dist; //sからの距離
    vector<int> iter; //どこまで調べたか
public:
    struct edge {
        int to, rev; long long cap;
        edge(int t = 0, int r = 0, long long c = 0LL) : to(t), rev(r), cap(c) {}
    };

    int n;
    vector<vector<edge>> to;

    Dinic(int n_ = 1) : n(n_), to(n_), dist(n_), iter(n_) {}

    void addedge(int u, int v, long long cap) {//u->vにcapの容量
        int su = (int)to[u].size(), sv = (int)to[v].size();
        to[u].push_back({ v, sv, cap });
        to[v].push_back({ u, su, 0 });
    }

    long long dfs(int v, int t, long long f) { //t: 終点, f: flow
        if (v == t) return f;
        int sv = (int)to[v].size();
        for (int& i = iter[v]; i < sv; i++) {
            edge& nv = to[v][i];
            if (dist[nv.to] <= dist[v] || nv.cap == 0) continue; //here
            long long nf = dfs(nv.to, t, min(f, nv.cap));
            if (nf > 0) {
                nv.cap -= nf;
                to[nv.to][nv.rev].cap += nf;
                return nf;
            }
        }
        return 0;
    }

    void bfs(int s) {
        dist.assign(n, -1);
        queue<int> q;
        q.push(s);
        dist[s] = 0;
        while (!q.empty()) {
            int v = q.front();
            q.pop();
            for (auto nv : to[v]) {
                if (nv.cap > 0 && dist[nv.to] < 0) {
                    dist[nv.to] = dist[v] + 1;
                    q.push(nv.to);
                }
            }
        }
    }

    long long maxflow(int s, int t) {//s:始点, t:終点
        long long res = 0, flow = 0;
        while (true) {
            bfs(s);
            if (dist[t] < 0) break;

            iter.assign(n, 0);
            while (flow = dfs(s, t, inf)) res += flow;
        };
        return res;
    }
};


int main()
{    
    int n;
    while (cin >> n, n) {
        int m;
        cin >> m;
        map<int, int> mp;
        rep(i, m) {
            int x;
            cin >> x;
            mp[x];
        }
        int idx = 0;
        for (auto& elem : mp) elem.second = idx++;

        Dinic dn(m + n + 2);
        int S = m + n, T = m + n + 1;
        rep(i, m) dn.addedge(S, i, 1);
        rep(i, n) dn.addedge(i + m, T, 1);

        rep(i, n) {
            int mg = 0;
            cin >> mg;
            rep(j, mg) {
                int x;
                cin >> x;
                if (mp.count(x)) dn.addedge(mp[x], i + m, 1);
            }
        }

        int flow = dn.maxflow(S, T);
        cout << flow << endl;
    }

    return 0;
}
accuracy: 1
time_ms: 80
memory_kb: 3696
final_rank: 14

code_snippet: #include <iostream>
#include <sstream>
#include <string>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <cassert>
 
using namespace std;
 
#define FOR(i,k,n) for(int i=(k); i<(int)(n); ++i)
#define REP(i,n) FOR(i,0,n)
#define FORIT(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
 
template<class T> void debug(T begin, T end){ for(T i = begin; i != end; ++i) cerr<<*i<<" "; cerr<<endl; }
inline bool valid(int x, int y, int W, int H){ return (x >= 0 && y >= 0 && x < W && y < H); }
 
typedef long long ll;
const int INF = 100000000;
const double EPS = 1e-8;
const int MOD = 1000000007;
int dx[8] = {1, 0, -1, 0, 1, -1, -1, 1};
int dy[8] = {0, 1, 0, -1, 1, 1, -1, -1};
 
struct edge { int to, cap, rev; };
const int MAX_V = 100000;
 
vector<edge> G[MAX_V];
int level[MAX_V];
int iter[MAX_V];
 
void add_edge(int from, int to, int cap){
  //printf("add %d -> %d (%d)\n", from, to, cap);
  G[from].push_back((edge){to, cap, G[to].size()});
  G[to].push_back((edge){from, 0, G[from].size()-1});
}
void bfs(int s){
  memset(level, -1, sizeof(level));
  queue<int> que;
  level[s] = 0;
  que.push(s);
  while(!que.empty()){
    int v = que.front(); que.pop();
    for(int i = 0; i < G[v].size(); i++){
      edge &e = G[v][i];
      if(e.cap > 0 && level[e.to] < 0){
        level[e.to] = level[v] + 1;
        que.push(e.to);
      }
    }
  }
}
 
int dfs(int v, int t, int f){
  if(v == t) return f;
  for (int &i = iter[v]; i < G[v].size(); i++){
    edge &e = G[v][i];
    if(e.cap > 0 && level[v] < level[e.to]){
      int d = dfs(e.to, t, min(f, e.cap));
      if(d > 0){
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}
 
int Denic(int s, int t){
  int flow = 0;
  while(true){
    bfs(s);
    if(level[t] < 0) break;;
    memset(iter, 0, sizeof(iter));
    int f;
    while((f = dfs(s, t, INF)) > 0){
      flow += f;
    }
  }
  return flow;
}
int main(){
  int N;
  while(cin>>N && N){
    REP(i, MAX_V) G[i].clear();
    int M; cin>>M;
    vector<int> myday;
    REP(i, M){
      int t; cin>>t;
      myday.push_back(t);
    }
    sort(myday.begin(), myday.end());
    REP(i, N){
      int M2;
      cin>>M2;
      while(M2--){
        int t; cin>>t;
        if(binary_search(myday.begin(), myday.end(), t)){
          int idx = lower_bound(myday.begin(), myday.end(), t) - myday.begin();
          add_edge(i, N + idx, 1);
        }
      }
    }
    const int S = N + M;
    const int G = S + 1;
    REP(i, N){
      add_edge(S, i, 1);
    }
    REP(i, M){
      add_edge(N + i, G, 1);
    }
    cout<<Denic(S, G)<<endl;
  }
  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 6232
final_rank: 19

code_snippet: #include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

#define NUM 3000


//辺を表す構造体(行先、容量、逆辺のインデックス)
struct Edge{
	Edge(int arg_to,int arg_capacity,int arg_rev_index){
		to = arg_to;
		capacity = arg_capacity;
		rev_index = arg_rev_index;
	}
	int to,capacity,rev_index;
};

int V,E;
int N;
map<int,int> MAP;
vector<Edge> G[NUM]; //グラフの隣接リスト表現
int dist[NUM]; //sourceからの距離
int cheked_index[NUM]; //どこまで調べ終わったか

//fromからtoへ向かう容量capacityの辺をグラフに追加する
void add_edge(int from,int to,int capacity){
	G[from].push_back(Edge(to,capacity,G[to].size()));
	G[to].push_back(Edge(from,0,G[from].size()-1)); //逆辺の、初期容量は0
}

//sourceからの最短距離をBFSで計算する
void bfs(int source){
	for(int i = 0; i < V; i++)dist[i] = -1;
	queue<int> Q;
	dist[source] = 0;
	Q.push(source);

	while(!Q.empty()){
		int node_id = Q.front();
		Q.pop();
		for(int i = 0; i < G[node_id].size(); i++){
			Edge &e = G[node_id][i];
			if(e.capacity > 0 && dist[e.to] < 0){ //辺の容量が正で、かつエッジの行先に未訪問の場合
				dist[e.to] = dist[node_id]+1;
				Q.push(e.to);
			}
		}
	}
}

//増加パスをDFSで探す
int dfs(int node_id,int sink,int flow){
	if(node_id == sink)return flow; //終点についたらflowをreturn

	for(int &i = cheked_index[node_id]; i < G[node_id].size(); i++){ //node_idから出ているエッジを調査
		Edge &e = G[node_id][i];
		if(e.capacity > 0 && dist[node_id] < dist[e.to]){ //流せる余裕があり、かつsourceからの距離が増加する方法である場合
			int tmp_flow = dfs(e.to,sink,min(flow,e.capacity)); //流せるだけ流す
			if(tmp_flow > 0){ //流せた場合
				e.capacity -= tmp_flow; //流した分、エッジの容量を削減する
				G[e.to][e.rev_index].capacity += tmp_flow; //逆辺の容量を、流した分だけ増加させる
				return tmp_flow;
			}
		}
	}
	return 0;
}


//sourceからsinkへの最大流を求める
int max_flow(int source,int sink){ //source:始点 sink:終点
	int flow = 0,add;
	while(true){ //増加パスが存在する限り、流量を追加し続ける
		bfs(source);
		if(dist[sink] < 0)break; //sourceからsinkへと辿り着く残余グラフがない、つまり増加パスが無くなった場合、break
		for(int i = 0; i < V; i++)cheked_index[i] = 0;
		while((add = dfs(source,sink,BIG_NUM)) > 0){ //増加パスが見つかる間、加算
			flow += add;
		}
	}
	return flow;
}

void func(){

	MAP.clear();
	for(int i = 0; i < NUM; i++)G[i].clear();

	int num,tmp,index = 2;
	scanf("%d",&num);

	int source = 0,sink = 1;

	for(int loop = 0; loop < num; loop++){
		scanf("%d",&tmp);
		MAP[tmp] = index;
		add_edge(source,index,1); //sourceからindexに、容量1の辺を張る
		index++;
	}

	int integrate;

	for(int loop = 0; loop < N; loop++){
		scanf("%d",&num);
		add_edge(index,sink,1); //1人の人物につき、最大流量1の集約路を張る
		integrate = index;
		index++;

		for(int i = 0; i < num; i++){
			scanf("%d",&tmp);
			auto at = MAP.find(tmp);
			if(at == MAP.end())continue; //Isaccの都合の良い日でなければ無視
			add_edge(MAP[tmp],integrate,1); //Isaccの都合の良い日から、
		}
	}

	V = index;

	printf("%d\n", max_flow(source,sink));
}


int main(){

	while(true){
		scanf("%d",&N);
		if(N == 0)break;

		func();
	}

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3476
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define r(i,n) for(int i=0;i<n;i++)
using namespace std;
struct Dinic{
  const int INF=1<<28;
  
  struct edge {
    int to,cap,rev;
    edge(){}
    edge(int to,int cap,int rev):to(to),cap(cap),rev(rev){}
  };

  int n;
  vector<vector<edge> > G;
  vector<map<int,int> > M;
  vector<int> level,iter;

  Dinic(){}
  Dinic(int sz):n(sz),G(n),M(n),level(n),iter(n){}
  
  void add_edge(int from,int to,int cap){
    M[from][to]=G[from].size();
    M[to][from]=G[to].size();
    G[from].push_back(edge(to,cap,G[to].size()));
    // undirected
    //G[to].push_back(edge(from,cap,G[from].size()-1));
    // directed
    G[to].push_back(edge(from,0,G[from].size()-1));
  }
  
  void bfs(int s){
    fill(level.begin(),level.end(),-1);
    queue<int> que;
    level[s]=0;
    que.push(s);
    while(!que.empty()){
      int v=que.front();que.pop();
      for(int i=0;i<(int)G[v].size();i++){
        edge &e = G[v][i];
        if(e.cap>0&&level[e.to]<0){
          level[e.to]=level[v]+1;
          que.push(e.to);
        }
      }
    }
  }
  
  int dfs(int v,int t,int f){
    if(v==t) return f;
    for(int &i=iter[v];i<(int)G[v].size();i++){
      edge &e=G[v][i];
      if(e.cap>0&&level[v]<level[e.to]){
        int d = dfs(e.to,t,min(f,e.cap));
       if(d>0){
         e.cap-=d;
         G[e.to][e.rev].cap+=d;
         return d;
       }
      }
    }
    return 0;
  }
  
  int flow(int s,int t,int lim){
    int fl=0;
    for(;;){
      bfs(s);
      if(level[t]<0||lim==0) return fl;
      fill(iter.begin(),iter.end(),0);
      int f;
      while((f=dfs(s,t,lim))>0){
       fl+=f;
       lim-=f;
      }
    }
  }

  int flow(int s,int t){
    return flow(s,t,INF);
  }

  //cap==1 only
  bool back_edge(int s,int t,int from, int to){
    for(int i=0;i<(int)G[from].size();i++) {
      edge& e=G[from][i];
      if(e.to==to) {
        if(e.cap==0&&flow(from,to,1)==0) {
          flow(from,s,1);
          flow(t,to,1);
          return 1;
        }
      }
    }
    return 0;
  }
};
int main(){
  int n,m,x,N;
  while(cin>>n,n){
    map<int,int>M;
    cin>>N;
    r(i,N){
      cin>>x;
      M[x]=i;
    }
    Dinic d(N+n+2);
    r(i,N)d.add_edge(N+n,i,1);
    r(i,n)d.add_edge(N+i,N+n+1,1);
    r(i,n){
      cin>>m;
      r(j,m){
        cin>>x;
        if(M.count(x))d.add_edge(M[x],N+i,1);
      }
    }
    cout<<d.flow(N+n,N+n+1,1e8)<<endl;
  }
}
accuracy: 1
time_ms: 110
memory_kb: 3676
final_rank: 16

code_snippet: #include "bits/stdc++.h"
using namespace std;
#ifdef _DEBUG
#include "dump.hpp"
#else
#define dump(...)
#endif

//#define int long long
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=(b)-1;i>=(a);i--)
#define all(c) begin(c),end(c)
const int INF = sizeof(int) == sizeof(long long) ? 0x3f3f3f3f3f3f3f3fLL : 0x3f3f3f3f;
const int MOD = (int)(1e9) + 7;
template<class T> bool chmax(T &a, const T &b) { if (a < b) { a = b; return true; } return false; }
template<class T> bool chmin(T &a, const T &b) { if (b < a) { a = b; return true; } return false; }

struct Dinic {
	using Flow = int;
	struct Edge {
		int to, rev;
		Flow cap;
		Edge() {}
		Edge(int to, int rev, Flow cap) :to(to), rev(rev), cap(cap) {}
	};
	int n;
	vector<vector<Edge>> g;
	vector<bool> used;
	vector<int> level;
	vector<int> iter;
	Dinic(int n) :n(n), g(n), used(n), level(n), iter(n) {};
	void addArc(int from, int to, Flow cap) {
		g[from].emplace_back(to, (int)g[to].size(), cap);
		g[to].emplace_back(from, (int)g[from].size() - 1, 0);
	}
	void addEdge(int a, int b, Flow cap) {
		g[a].emplace_back(b, (int)g[b].size(), cap);
		g[b].emplace_back(a, (int)g[a].size() - 1, cap);
	}
	Flow maximumFlow(int s, int t) {
		Flow total = 0;
		while (true) {
			levelize(s);
			if (level[t] < 0)return total;
			fill(iter.begin(), iter.end(), 0);
			Flow f;
			while (true) {
				f = augment(s, t, INF);
				if (f == 0)break;
				total += f;
			}
		}
	}
	Flow augment(int v, int t, Flow f) {
		if (v == t)return f;
		for (int &i = iter[v]; i < g[v].size(); i++) {
			Edge &e = g[v][i];
			if (e.cap > 0 && level[v] < level[e.to]) {
				Flow d = augment(e.to, t, min(f, e.cap));
				if (d > 0) {
					e.cap -= d;
					g[e.to][e.rev].cap += d;
					return d;
				}
			}
		}
		return 0;
	}
	void levelize(int s) {
		fill(level.begin(), level.end(), -1);
		queue<int> q;
		level[s] = 0;
		q.push(s);
		while (q.size()) {
			int v = q.front(); q.pop();
			for (int i = 0; i < g[v].size(); i++) {
				Edge &e = g[v][i];
				if (e.cap > 0 && level[e.to] < 0) {
					level[e.to] = level[v] + 1;
					q.push(e.to);
				}
			}
		}
	}
};

signed main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	for (int N; cin >> N&&N;) {
		int M; cin >> M;
		Dinic dinic(M + N + 2);
		int s = dinic.n - 2, t = s + 1;
		unordered_map<int, int> mp;
		rep(i, 0, M) { int d; cin >> d; mp[d] = i; }
		rep(i, 0, N) {
			int m; cin >> m;
			rep(j, 0, m) {
				int d; cin >> d;
				if (mp.count(d))
					dinic.addArc(mp[d], M + i, 1);
			}
		}
		rep(i, 0, M)dinic.addArc(s, i, 1);
		rep(i, 0, N)dinic.addArc(M + i, t, 1);
		cout << dinic.maximumFlow(s, t) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3288
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define fi first
#define se second
#define dbg(x) cout<<#x" = "<<((x))<<endl
template<class T,class U> ostream& operator<<(ostream& o, const pair<T,U> &p){o<<"("<<p.fi<<","<<p.se<<")";return o;}
template<class T> ostream& operator<<(ostream& o, const vector<T> &v){o<<"[";for(T t:v){o<<t<<",";}o<<"]";return o;}

struct edge{int to,cap,rev;};

const int MAX_V = 2000;
const int F_INF = 19191919;
vector<edge> G[MAX_V];
int lv[MAX_V], it[MAX_V];

void add_edge(int from, int to, int cap){
    G[from].pb({to,cap,(int)G[to].size()});
    G[to].pb({from,0,(int)G[from].size()-1});
}

void dinic_bfs(int s){
    fill(lv,lv+MAX_V,-1);
    queue<int> que;
    lv[s]=0;
    que.push(s);
    while(!que.empty()){
        int v = que.front(); que.pop();
        rep(i,G[v].size()){
            edge &e = G[v][i];
            if(e.cap>0 && lv[e.to]<0){
                lv[e.to] = lv[v]+1;
                que.push(e.to);
            }
        }
    }
}

int dinic_dfs(int v, int t, int f){
    if(v==t) return f;
    for(int &i=it[v]; i<G[v].size(); ++i){
        edge &e = G[v][i];
        if(e.cap>0 && lv[v]<lv[e.to]){
            int d = dinic_dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap -= d;
                G[e.to][e.rev].cap += d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(int s, int t){
    int flow = 0;
    while(1){
        dinic_bfs(s);
        if(lv[t]<0) return flow;
        fill(it,it+MAX_V,0);
        int f;
        while((f=dinic_dfs(s,t,F_INF))>0) flow+=f;
    }
}

int main()
{
    int n;
    while(scanf(" %d", &n),n)
    {
        rep(i,MAX_V) G[i].clear();

        unordered_map<int,int> m;
        int M = 0;

        int ISSAC;
        scanf(" %d", &ISSAC);
        while(ISSAC--)
        {
            int day;
            scanf(" %d", &day);
            if(!m.count(day)) m[day] = M++;
        }

        vector<int> k(n);
        vector<vector<int>> s(n);

        rep(i,n)
        {
            scanf(" %d", &k[i]);
            rep(j,k[i])
            {
                int day;
                scanf(" %d", &day);
                if(m.count(day)) s[i].pb(m[day]);
            }
            k[i] = s[i].size();
        }

        int S = n+M, T = S+1;
        rep(i,n)
        {
            add_edge(S,i,1);
            rep(j,k[i]) add_edge(i,n+s[i][j],1);
        }
        rep(i,M) add_edge(n+i,T,1);

        printf("%d\n", max_flow(S,T));
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3688
final_rank: 11

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, n) for(int i = 0; i < (int)(n); i++)
#define reps(i, s, n) for(int i = (int)(s); i < (int)(n); i++)

const int inf = 1e9;

#define MAX_V 3000

struct edge {
  int to, cap, rev;
  edge(){}
  edge(int to, int cap, int rev):to(to), cap(cap), rev(rev){}
};
vector<edge> graph[MAX_V];
int level[MAX_V], iter[MAX_V];
void add_edge(int from, int to, int cap) {
  graph[from].emplace_back(to, cap, (int)graph[to].size());
  graph[to].emplace_back(from, 0, (int)graph[from].size()-1);
}
void bfs(int s) {
  memset(level, -1, sizeof(level));
  level[s] = 0;
  queue<int> que;
  que.push(s);
  while(que.size()) {
    int v = que.front(); que.pop();
    for(edge& e : graph[v]) {
      if(e.cap > 0 && level[e.to] < 0) {
	level[e.to] = level[v] + 1;
	que.push(e.to);
      }
    }
  }
}
int dfs(int v, int t, int f) {
  if(v == t) return f;
  for(int& i = iter[v]; i < (int)graph[v].size(); i++) {
    edge& e = graph[v][i];
    if(e.cap > 0 && level[v] < level[e.to]) {
      int d = dfs(e.to, t, min(e.cap, f));
      if(d > 0) {
	e.cap -= d;
	graph[e.to][e.rev].cap += d;
	return d;
      }
    }
  }
  return 0;
}
int max_flow(int s, int t) {
  int flow = 0;
  while(1) {
    bfs(s);
    if(level[t] < 0) return flow;
    memset(iter, 0, sizeof(iter));
    int f; while((f = dfs(s, t, inf)) > 0) flow += f;
  }
}


int N, M;
map<int, int> mp;

signed main()
{
  cin.tie(0);
  ios_base::sync_with_stdio(0);
  cout << fixed << setprecision(12);

  while(cin >> N, N) {
    int s = 0, t = 1, V = 2;
    rep(i, MAX_V) graph[i].clear();
    mp.clear();
    cin >> M;
    rep(i, M) {
      int d; cin >> d;
      mp[d] = V++;
    }
    for(auto p : mp) add_edge(s, p.second, 1);
    rep(i, N) {
      cin >> M;
      rep(j, M) {
	int d; cin >> d;
	if(mp.count(d)) add_edge(mp[d], V+i, 1);
      }
      add_edge(V+i, t, 1);
    }
    cout << max_flow(s, t) << endl;
  }

  return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3268
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;

struct BipartiteMatching {
	int V;
	vector<vector<bool> > G;
	vector<int> match;
	vector<bool> used;

	BipartiteMatching(int v) {
		V = v;
		G = vector<vector<bool> >(v, vector<bool>(v));
		match = vector<int>(v);
		used = vector<bool>(v);
	}

	void add_edge(int v, int u) {
		G[v][u] = G[u][v] = true;
	}

	bool dfs(int v) {
		used[v] = true;
		for(int i = 0; i < V; i++) {
			if(!G[v][i]) continue;
			int u = i, w = match[u];
			if(w < 0 || (!used[w] && dfs(w))) {
				match[v] = u;
				match[u] = v;
				return true;
			}
		}
		return false;
	}

	int calc() {
		int res = 0;
		fill(match.begin(), match.end(), -1);
		for(int v = 0; v < V; v++) {
			if(match[v] < 0) {
				fill(used.begin(), used.end(), false);
				if(dfs(v)) {
					res++;
				}
			}
		}
		return res;
	}
};


int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	int N;
	while(cin >> N, N) {
		int M;
		cin >> M;
		map<int, int> id;
		for(int i = 0; i < M; i++) {
			int a;
			cin >> a;
			id[a] = -1;
		}
		int cnt = 0;
		for(auto v : id) {
			id[v.first] = cnt++;
		}

		BipartiteMatching bm(cnt + N);
		for(int i = 0; i < N; i++) {
			cin >> M;
			for(int j = 0; j < M; j++) {
				int a;
				cin >> a;
				if(id.count(a) == 0) continue;
				bm.add_edge(id[a], cnt + i);
			}
		}

		cout << bm.calc() << endl;
	}

}
accuracy: 1
time_ms: 250
memory_kb: 3256
final_rank: 18

code_snippet: #include <bits/stdc++.h>
 
using namespace std;
 
#define REP(i,a,b) for(int i=a;i<(int)b;i++)
#define rep(i,n) REP(i,0,n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a) { cout << #a << " = " << a << endl; }
template<class T1, class T2> inline bool minimize(T1 &a, T2 b) { return b < a && (a = b, 1); }
template<class T1, class T2> inline bool maximize(T1 &a, T2 b) { return a < b && (a = b, 1); }
 
typedef long long ll;
int const inf = 1<<29;
 
namespace flow {
 
class bipartite_matching {
private:
 
  int V;
  vector<vector<int>> G;
  vector<int> match;
  vector<bool> used;
 
  bool dfs(int v) {
    used[v] = 1;
    for(auto& u: G[v]) {
      int w = match[u];
      if(w < 0 || (!used[w] && dfs(w))) {
        match[v] = u;
        match[u] = v;
        return true;
      }
    }
    return false;
  }
 
 
public:
 
  bipartite_matching(int V): V(V) {
    G.resize(V), match.resize(V), used.resize(V);
  }
 
  void add_edge(int u, int v) {
    G[u].push_back(v);
    G[v].push_back(u);
  }
 
  int maximum_matching() {
    int ret = 0;
    match.clear(), match.resize(V, -1);
    rep(v, V) {
      if(match[v] < 0) {
        used.clear(), used.resize(V, 0);
        if(dfs(v)) { ret ++; }
      }
    }
    return ret;
  }
};
 
}
 
int main() {
 
  for(int N; cin >> N && N;) {
    int M; cin >> M;
 
    int dcnt = 0;
    unordered_map<int, int> dayidx;
    rep(i, M) {
      int x; cin >> x;
      if(dayidx.find(x) == dayidx.end()) {
        dayidx[x] = dcnt++;
      }
    }
 
    flow::bipartite_matching bp(dcnt + N);
 
    rep(girl, N) {
      cin >> M;
      rep(i, M) {
        int k; cin >> k;
        if(dayidx.find(k) != dayidx.end())
          bp.add_edge(dayidx[k], dcnt + girl);
      }
    }
 
    cout << bp.maximum_matching() << endl;
  }
   
  return 0;
}
accuracy: 1
time_ms: 110
memory_kb: 3212
final_rank: 15

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define REP(i,a,b) for(int i=a;i<(int)b;i++)
#define rep(i,n) REP(i,0,n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a) { cout << #a << " = " << a << endl; }
template<class T1, class T2> inline bool minimize(T1 &a, T2 b) { return b < a && (a = b, 1); }
template<class T1, class T2> inline bool maximize(T1 &a, T2 b) { return a < b && (a = b, 1); }

typedef long long ll;
int const inf = 1<<29;

namespace flow {

class bipartite_matching {
private:

  int V;
  vector<vector<int>> G;
  vector<int> match;
  vector<bool> used;

  bool dfs(int v) {
    used[v] = 1;
    for(auto& u: G[v]) {
      int w = match[u];
      if(w < 0 || (!used[w] && dfs(w))) {
        match[v] = u;
        match[u] = v;
        return true;
      }
    }
    return false;
  }


public:

  bipartite_matching(int V): V(V) {
    G.resize(V), match.resize(V), used.resize(V);
  }

  void add_edge(int u, int v) {
    G[u].push_back(v);
    G[v].push_back(u);
  }

  int maximum_matching() {
    int ret = 0;
    match.clear(), match.resize(V, -1);
    rep(v, V) {
      if(match[v] < 0) {
        used.clear(), used.resize(V, 0);
        if(dfs(v)) { ret ++; }
      }
    }
    return ret;
  }
};

}

int main() {

  for(int N; cin >> N && N;) {
    int M; cin >> M;

    int dcnt = 0;
    map<int, int> dayidx;
    rep(i, M) {
      int x; cin >> x;
      if(dayidx.find(x) == dayidx.end()) {
        dayidx[x] = dcnt++;
      }
    }

    flow::bipartite_matching bp(dcnt + N);

    rep(girl, N) {
      cin >> M;
      rep(i, M) {
        int k; cin >> k;
        if(dayidx.find(k) != dayidx.end())
          bp.add_edge(dayidx[k], dcnt + girl);
      }
    }

    cout << bp.maximum_matching() << endl;
  }
  
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 3232
final_rank: 17

code_snippet: #include <bits/stdc++.h>
 
using namespace std;
 
#define MAX_V 3000
#define INF 1e9
 
struct edge{ int to,cap,rev; };
 
vector<edge> G[MAX_V];
int level[MAX_V],iter[MAX_V];
 
void add_edge(int from,int to,int cap){
    G[from].push_back((edge){to,cap,G[to].size()});
    G[to].push_back((edge){from,0,G[from].size()-1});
}
 
void bfs(int s){
    memset(level,-1,sizeof(level));
    queue<int> Q;
    level[s] = 0;
    Q.push(s);
    while(!Q.empty()){
	int v = Q.front(); Q.pop();
	for(int i = 0 ; i < (int)G[v].size() ; i++){
	    edge &e = G[v][i];
	    if(e.cap > 0 && level[e.to] < 0){
		level[e.to] = level[v] + 1;
		Q.push(e.to);
	    }
	}
    }
}
 
int dfs(int v,int t,int f){
    if(v == t) return f;
    for(int &i = iter[v] ; i < (int)G[v].size() ; i++){
	edge &e = G[v][i];
	if(e.cap > 0 && level[v] < level[e.to]){
	    int d = dfs(e.to,t,min(f,e.cap));
	    if(d > 0){
		e.cap -= d;
		G[e.to][e.rev].cap += d;
		return d;
	    }
	}
    }
    return 0;
}
 
int max_flow(int s,int t){
    int flow = 0;
    for(;;){
	bfs(s);
	if(level[t] < 0) return flow;
	memset(iter,0,sizeof(iter));
	int f;
	while((f = dfs(s,t,INF)) > 0){
	    flow += f;
	}
    }
}
 
int main(){
    int N;
    while(cin >> N,N){
	for(int i = 0 ; i < MAX_V ; i++){
	    G[i].clear();
	}
	int k,x,n;
	cin >> n;
	int S = N+n,T = S+1;
	map<int,int> mp;
	for(int i = 0 ; i < n ; i++){
	    cin >> x;
	    mp[x] = i;
	}
	map<int,int>::iterator it;
	for(it = mp.begin() ; it != mp.end() ; ++it){
	    add_edge(S,it->second,1);
	}
	for(int i = 0 ; i < N ; i++){
	    cin >> k;
	    for(int j = 0 ; j < k ; j++){
		cin >> x;
		if(mp.find(x) != mp.end()){
		    add_edge(mp[x],n+i,1);
		}
	    }
	    add_edge(n+i,T,1);
	}
	cout << max_flow(S,T) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 1532
final_rank: 3

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define MAX_V 3000
#define INF 1e9

struct edge{ int to,cap,rev; };

vector<edge> G[MAX_V];
int level[MAX_V],iter[MAX_V];

void add_edge(int from,int to,int cap){
  G[from].push_back((edge){to,cap,G[to].size()});
  G[to].push_back((edge){from,0,G[from].size()-1});
}

void bfs(int s){
  memset(level,-1,sizeof(level));
  queue<int> Q;
  level[s] = 0;
  Q.push(s);
  while(!Q.empty()){
    int v = Q.front(); Q.pop();
    for(int i = 0 ; i < (int)G[v].size() ; i++){
      edge &e = G[v][i];
      if(e.cap > 0 && level[e.to] < 0){
        level[e.to] = level[v] + 1;
        Q.push(e.to);
      }
    }
  }
}

int dfs(int v,int t,int f){
  if(v == t) return f;
  for(int &i = iter[v] ; i < (int)G[v].size() ; i++){
    edge &e = G[v][i];
    if(e.cap > 0 && level[v] < level[e.to]){
      int d = dfs(e.to,t,min(f,e.cap));
      if(d > 0){
        e.cap -= d;
        G[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}

int max_flow(int s,int t){
  int flow = 0;
  for(;;){
    bfs(s);
    if(level[t] < 0) return flow;
    memset(iter,0,sizeof(iter));
    int f;
    while((f = dfs(s,t,INF)) > 0){
      flow += f;
    }
  }
}

int main(){
  int N;
  while(cin >> N,N){
    for(int i = 0 ; i < MAX_V ; i++){
      G[i].clear();
    }
    int k,x,n;
    cin >> n;
    int S = N+n,T = S+1;
    map<int,int> mp;
    for(int i = 0 ; i < n ; i++){
      cin >> x;
      mp[x] = i;
    }
    map<int,int>::iterator it;
    for(it = mp.begin() ; it != mp.end() ; ++it){
      add_edge(S,it->second,1);
    }
    for(int i = 0 ; i < N ; i++){
      cin >> k;
      for(int j = 0 ; j < k ; j++){
        cin >> x;
        if(mp.find(x) != mp.end()){
          add_edge(mp[x],n+i,1);
        }
      }
      add_edge(n+i,T,1);
    }
    cout << max_flow(S,T) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 1532
final_rank: 3

code_snippet: #include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
const int D_MAX_V=2102;
const int D_v_size=2102;
struct D_wolf{
	int t,c,r;
	D_wolf(){t=c=r=0;}
	D_wolf(int t1,int c1,int r1){
		t=t1;c=c1;r=r1;
	}
};
vector<D_wolf>D_G[D_MAX_V];
int D_level[D_MAX_V];
int D_iter[D_MAX_V];

void add_edge(int from,int to,int cap){
	D_G[from].push_back(D_wolf(to,cap,D_G[to].size()));
	D_G[to].push_back(D_wolf(from,0,D_G[from].size()-1));
}
void D_bfs(int s){
	for(int i=0;i<D_v_size;i++)D_level[i]=-1;
	queue<int> Q;
	D_level[s]=0;
	Q.push(s);
	while(Q.size()){
		int v=Q.front();
		Q.pop();
		for(int i=0;i<D_G[v].size();i++){
			if(D_G[v][i].c>0&&D_level[D_G[v][i].t]<0){
				D_level[D_G[v][i].t]=D_level[v]+1;
				Q.push(D_G[v][i].t);
			}
		}
	}
}
int D_dfs(int v,int t,int f){
	if(v==t)return f;
	for(;D_iter[v]<D_G[v].size();D_iter[v]++){
		int i=D_iter[v];
		if(D_G[v][i].c>0&&D_level[v]<D_level[D_G[v][i].t]){
			int d=D_dfs(D_G[v][i].t,t,min(f,D_G[v][i].c));
			if(d>0){
				D_G[v][i].c-=d;
				D_G[D_G[v][i].t][D_G[v][i].r].c+=d;
				return d;
			}
		}
	}
	return 0;
}
int max_flow(int s,int t){
	int flow=0;
	for(;;){
		D_bfs(s);
		if(D_level[t]<0)return flow;
		for(int i=0;i<D_v_size;i++)D_iter[i]=0;
		int f;
		while((f=D_dfs(s,t,99999999))>0){flow+=f;}
	}
	return 0;
}
int main(){
	int a;
	while(scanf("%d",&a),a){
		for(int i=0;i<2102;i++){
			D_G[i].clear();
			D_iter[i]=D_level[i]=0;
		}
		int n;scanf("%d",&n);
		map<int,int>c;
		for(int i=0;i<n;i++){
			int b;scanf("%d",&b);
			c[b]=i;
		}
		int s=2100;
		int t=2101;
		for(int i=0;i<n;i++)add_edge(s,i,1);
		for(int i=0;i<a;i++){
			int m;scanf("%d",&m);
			for(int j=0;j<m;j++){
				int p;scanf("%d",&p);
				if(c.count(p)){
					add_edge(c[p],i+n,1);
				}
			}
		}
		for(int i=0;i<a;i++)add_edge(i+n,t,1);
		printf("%d\n",max_flow(s,t));
	}
}
accuracy: 1
time_ms: 80
memory_kb: 1268
final_rank: 1

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <cassert>
#include <queue>
#include <cstring>
using namespace std;
static const double EPS = 1e-9;
typedef long long ll;
#define rep(i,n) for(int i=0;i<n;i++)
#define rev(i,n) for(int i=n-1;i>=0;i--)
#define sz(a) a.size()
#define all(a) a.begin(),a.end()
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define SS stringstream
#define DBG1(a) rep(_X,sz(a)){printf("%d ",a[_X]);}puts("");
#define DBG2(a) rep(_X,sz(a)){rep(_Y,sz(a[_X]))printf("%d ",a[_X][_Y]);puts("");}
#define bitcount(b) __builtin_popcount(b)
#define fi first
#define se second

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()

typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
  Edge(int src, int dst) :
    src(src), dst(dst), weight(0) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

bool augment(const Graph& g, int u,
    vector<int>& matchTo, vector<bool>& visited) {
  if (u < 0) return true;
  FOR(e, g[u]) if (!visited[e->dst]) {
    visited[e->dst] = true;
    if (augment(g, matchTo[e->dst], matchTo, visited)) {
      matchTo[e->src] = e->dst;
      matchTo[e->dst] = e->src;
      return true;
    }
  }
  return false;
}
int bipartiteMatching(const Graph& g, int L, Edges& matching) {
  const int n = g.size();
  vector<int> matchTo(n, -1);
  int match = 0;
  REP(u, L) {
    vector<bool> visited(n);
    if (augment(g, u, matchTo, visited)) ++match;
  }
  REP(u, L) if (matchTo[u] >= 0) // make explicit matching
    matching.push_back( Edge(u, matchTo[u]) );
  return match;
}

int main(){
	int N;
	while(cin >> N && N){
		set<int> w;
		int a,b;
		cin >> a;
		vector<int> day;
		for(int i = 0 ; i < a ; i++){
			cin >> b;
			b--;
			w.insert(b);
			day.push_back(b);
		}
		Edges edge;
		for(int i = 0 ; i < N ; i++){
			int t;
			cin >> t;
			for(int j = 0 ; j < t ; j++){
				int s;
				cin >> s;
				s--;
				if(w.count(s)) edge.push_back(Edge(i,s));
				day.push_back(s);
			}
		}
		sort(day.begin(),day.end());
		day.erase(unique(day.begin(),day.end()),day.end());
		int ub = max(N,(int)day.size());
		Graph g(2*ub);
		for(int i = 0 ; i < edge.size() ; i++){
			int a = edge[i].src;
			int b = ub + lower_bound(day.begin(),day.end(),edge[i].dst) - day.begin();
			g[a].push_back(Edge(a,b));
			g[b].push_back(Edge(b,a));
			//cout << a << " " << b << endl;
		}
		Edges tmp;
		cout << bipartiteMatching(g,ub,tmp) << endl;
		
		
	}
}
accuracy: 1
time_ms: 310
memory_kb: 4820
final_rank: 20

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>
 
#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29) 
#define all(n) (n).begin(),(n).end()
#define MAX_V 1100
using namespace std;
 
//follow
struct edge
{
  int to,cap,rev;
  edge(int to=inf,int cap=inf,int rev=inf):to(to),cap(cap),rev(rev){}
};
  
vector<edge> G[MAX_V];
int level[MAX_V];
int iter[MAX_V];
bool used[MAX_V];
  
void init(int V)
{
  rep(i,V)G[i].clear();
}
  
void add_edge(int from,int to,int cap)
{
  G[from].push_back(edge(to,cap,G[to].size()));
  G[to].push_back(edge(from,0,G[from].size()-1));
}
 
int dfs(int v,int t,int f)
{
  if(v == t)return f;
  used[v] = true;
  for(int i=0;i<G[v].size();i++)
    {
      edge &e = G[v][i];
      if(e.cap > 0 && !used[e.to])
    {
      int d = dfs(e.to,t,min(f,e.cap));
      if(d > 0)
        {
          e.cap -= d;
          G[e.to][e.rev].cap += d;
          return d;
        }
    }
    }
  return 0;
}
  
int max_flow(int s,int t)
{
  int flow = 0;
  for(;;)
    {
      memset(used,0,sizeof(used));
      int f = dfs(s,t,inf);
      if(f == 0)
    {
      return flow;
    }
      flow += f;
    }
}
  
//
 
int main()
{
  int N,k,K,s,t,day;
  while(cin >> N,N)
    {
      cin >> k;
      K = k;
      s = k + N;
      t = s + 1;
      init(t+1);
      map<int,int> days;
      vector<int> vday;
      rep(i,k)
    {
      cin >> day;
      vday.push_back(day);
    }
      sort(all(vday));
      vday.erase(unique(all(vday)),vday.end());
      rep(i,vday.size())
    {
      days[vday[i]] = i;
      add_edge(s,i,1);
    }
 
      rep(i,N)
    {
      cin >> k;
      rep(j,k)
        {
          cin >> day;
          if(days.find(day) != days.end())
        {
          add_edge(days[day],K+i,1);
        }
        }
      add_edge(K+i,t,1);
    }
 
      cout << max_flow(s,t) << endl;
 
    }
  return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 1536
final_rank: 10

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<cassert>
#include<map>

#define MAX_V 5000
#define INF (1<<29)

using namespace std;

struct edge{int to,cap,rev;};

vector<edge>g[MAX_V];
bool used[MAX_V];

void add_edge(int from,int to,int cap){
  g[from].push_back((edge){to,cap,g[to].size()});
  g[to].push_back((edge){from,0,g[from].size()-1});
}

int dfs(int v,int t,int f){
  if(v==t)return f;
  used[v]=true;
  for(int i=0;i<g[v].size();i++){
    edge &e=g[v][i];
    if(!used[e.to] && e.cap>0){
      int d=dfs(e.to,t,min(f,e.cap));
      if(d>0){
        e.cap-=d;
        g[e.to][e.rev].cap+=d;
        return d;
      }
    }
  }
  return 0;
}

int max_flow(int s,int t){
  int flow=0;
  for(;;){
    fill(used,used+MAX_V,false);
    int f=dfs(s,t,INF);
    if(f==0)return flow;
    flow+=f;
  }
}

int main(void){

  int n;
  while(cin >> n,n){

    for(int i=0;i<MAX_V;i++)g[i].clear();

    vector<int>a;
    map<int,int>mp;
    int m,in,tmp;
    cin >> tmp;
    for(int i=0;i<tmp;i++){
      cin >> in;
      add_edge(n+tmp,i,1);
      a.push_back(in);
      mp[in]=i;
    }

    for(int i=0;i<n;i++){
      cin >> m;
      vector<int>b(m);
      for(int j=0;j<m;j++)cin >> b[j];
      for(int j=0;j<m;j++){
        if(mp.count(b[j])){
          add_edge(mp[b[j]],i+tmp,1);
        }
      }
    }

    for(int i=0;i<n;i++){
      add_edge(i+tmp,n+tmp+1,1);
    }
    cout << max_flow(n+tmp,n+tmp+1) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 1532
final_rank: 8

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<cassert>
#include<map>

#define MAX_V 5000
#define INF (1<<29)

using namespace std;

struct edge{int to,cap,rev;};

vector<edge>g[MAX_V];
bool used[MAX_V];

void add_edge(int from,int to,int cap){
  g[from].push_back((edge){to,cap,g[to].size()});
  g[to].push_back((edge){from,0,g[from].size()-1});
}

int dfs(int v,int t,int f){
  if(v==t)return f;
  used[v]=true;
  for(int i=0;i<g[v].size();i++){
    edge &e=g[v][i];
    if(!used[e.to] && e.cap>0){
      int d=dfs(e.to,t,min(f,e.cap));
      if(d>0){
        e.cap-=d;
        g[e.to][e.rev].cap+=d;
        return d;
      }
    }
  }
  return 0;
}

int max_flow(int s,int t){
  int flow=0;
  for(;;){
    fill(used,used+MAX_V,false);
    int f=dfs(s,t,INF);
    if(f==0)return flow;
    flow+=f;
  }
}
int main(void){

  int n;
  while(cin >> n,n){

    for(int i=0;i<MAX_V;i++)g[i].clear();

    vector<int>a;
    map<int,int>mp;
    int m,in,tmp;
    cin >> tmp;
    for(int i=0;i<tmp;i++){
      cin >> in;
      add_edge(n+tmp,i,1);
      a.push_back(in);
      mp[in]=i;
    }

    for(int i=0;i<n;i++){
      cin >> m;
      vector<int>b(m);
      for(int j=0;j<m;j++)cin >> b[j];
      for(int j=0;j<m;j++){
        if(mp.count(b[j])){
          add_edge(mp[b[j]],i+tmp,1);
        }
      }
    }

    for(int i=0;i<n;i++){
      add_edge(i+tmp,n+tmp+1,1);
    }
    cout << max_flow(n+tmp,n+tmp+1) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 1532
final_rank: 8

code_snippet: #include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<cstring>

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define inf (1<<29) 
#define all(n) (n).begin(),(n).end()
#define MAX_V 1100
using namespace std;

//follow
struct edge
{
  int to,cap,rev;
  edge(int to=inf,int cap=inf,int rev=inf):to(to),cap(cap),rev(rev){}
};
 
vector<edge> G[MAX_V];
int level[MAX_V];
int iter[MAX_V];
bool used[MAX_V];
 
void init(int V)
{
  rep(i,V)G[i].clear();
}
 
void add_edge(int from,int to,int cap)
{
  G[from].push_back(edge(to,cap,G[to].size()));
  G[to].push_back(edge(from,0,G[from].size()-1));
}

int dfs(int v,int t,int f)
{
  if(v == t)return f;
  used[v] = true;
  for(int i=0;i<G[v].size();i++)
    {
      edge &e = G[v][i];
      if(e.cap > 0 && !used[e.to])
	{
	  int d = dfs(e.to,t,min(f,e.cap));
	  if(d > 0)
	    {
	      e.cap -= d;
	      G[e.to][e.rev].cap += d;
	      return d;
	    }
	}
    }
  return 0;
}
 
int max_flow(int s,int t)
{
  int flow = 0;
  for(;;)
    {
      memset(used,0,sizeof(used));
      int f = dfs(s,t,inf);
      if(f == 0)
	{
	  return flow;
	}
      flow += f;
    }
}
 
//

int main()
{
  int N,k,K,s,t,day;
  while(cin >> N,N)
    {
      cin >> k;
      K = k;
      s = k + N;
      t = s + 1;
      init(t+1);
      map<int,int> days;
      vector<int> vday;
      rep(i,k)
	{
	  cin >> day;
	  vday.push_back(day);
	}
      sort(all(vday));
      vday.erase(unique(all(vday)),vday.end());
      rep(i,vday.size())
	{
	  days[vday[i]] = i;
	  add_edge(s,i,1);
	}

      rep(i,N)
	{
	  cin >> k;
	  rep(j,k)
	    {
	      cin >> day;
	      if(days.find(day) != days.end())
		{
		  add_edge(days[day],K+i,1);
		}
	    }
	  add_edge(K+i,t,1);
	}

      cout << max_flow(s,t) << endl;

    }
  return 0;
}
accuracy: 1
time_ms: 140
memory_kb: 1536
final_rank: 5