Problem:
F: Clique Drawing
問題文
$M$ 回操作を行って $N$ 頂点のグラフを作ります。
初め、$N$ 頂点のどの頂点間にも辺は存在しません。
$i$ 番目の操作では、頂点集合 $\{ v_{i, 1}, v_{i, 2}, ... , v_{i, K_i} \}$ の全ての $2$ 頂点間に辺を張ります。ただし、以前の操作によって既に辺が貼られている頂点間には張りません。
また、どの頂点も $M$ 回の操作の内高々 $2$ 回の操作にしか現れません。
これらの操作によって出来たグラフ上の、最大独立集合の大きさを求めてください。
無向グラフ $G = (V, E)$ の独立集合 $U$ とは、$U \subseteq V$ なる頂点の部分集合であって、全ての $u, v \in U$ について、$(u, v) \notin E$ を満たすものを指します。
最大独立集合とは、このような独立集合の内、最も大きいものを指します。
制約
入力は全て整数
$1 \leq N \leq 10^5$
$1 \leq M \leq 300$
$2 \leq K_i \leq N$ ($1 \leq i \leq M$)
$1 \leq v_{i, j} \leq N$ ($1 \leq i \leq M, 1 \leq j \leq K_i$)
$\{ v_{i, 1}, v_{i, 2}, ... , v_{i, K_i} \}$ の中に重複した値は存在しない ($1 \leq i \leq M$)
全ての頂点は最大でも2回の操作にしか含まれない
入力
入力は以下の形式で標準入力から与えられます。
$N$ $M$
$K_1$ $v_{1, 1}$ $\ldots$ $v_{1, K_1}$
$\vdots$
$K_M$ $v_{M, 1}$ $\ldots$ $v_{M, K_M}$
出力
答えを一行で出力してください。
入出力例
入力例1
2 1
2 1 2
出力例1
1
1回の操作の後、2頂点からなる道が出来ます。
したがって、最大独立集合の大きさは1です。
入力例2
4 1
3 1 2 3
出力例2
2
入力例3
6 3
3 2 3 5
3 3 4 6
3 1 2 4
出力例3
3

Submitted solutions:

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

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
* @brief template
*/

class GeneralWeightedMatching{
    struct E{int u,v; ll w;};
    int n,m,in;
    vector<vector<E>> G;
    vector<int> mate,slack,root,par,isS,used;
    vector<vector<int>> flower,belong;
    vector<ll> dual;
    queue<int> que;
    
    ll dist(const E& e){return dual[e.u]+dual[e.v]-e.w;}
    void update(int u,int v){
        if(!slack[v] or dist(G[u][v])<dist(G[slack[v]][v]))slack[v]=u;
    }
    void recalc(int v){
        slack[v]=0;
        rep(i,1,n+1)if(G[i][v].w and root[i]!=v and isS[root[i]]==1)update(i,v);
    }
    void push(int v){
        if(v<=n)que.push(v);
        else for(auto& nxt:flower[v])push(nxt);
    }
    void set(int v,int rt){
        root[v]=rt;
        if(v>n)for(auto& nxt:flower[v])set(nxt,rt);
    }
    int findeven(int b,int v){
        int pos=find(ALL(flower[b]),v)-flower[b].begin();
        if(pos&1){
            reverse(flower[b].begin()+1,flower[b].end());
            pos=flower[b].size()-pos;
        }
        return pos;
    }
    void match(int u,int v){
        mate[u]=G[u][v].v;
        if(u>n){
            int x=belong[u][G[u][v].u];
            int pos=findeven(u,x);
            rep(i,0,pos)match(flower[u][i],flower[u][i^1]);
            match(x,v);
            rotate(flower[u].begin(),flower[u].begin()+pos,flower[u].end());
        }
    }
    void link(int u,int v){
        for(;;){
            int nv=root[mate[u]];
            match(u,v);
            if(!nv)break;
            v=nv,u=root[par[nv]];
            match(v,u);
        }
    }
    void make(int u,int v,int lca){
        int id=n+1;
        while(id<=m and root[id])id++;
        if(id>m)m++;
        flower[id].clear();
        rep(i,1,m+1)G[id][i].w=G[i][id].w=0;
        rep(i,1,n+1)belong[id][i]=0;
        isS[id]=1,dual[id]=0,mate[id]=mate[lca];
        while(u!=lca){
            flower[id].push_back(u);
            u=root[mate[u]];
            push(u);
            flower[id].push_back(u);
            u=root[par[u]];
        }
        flower[id].push_back(lca);
        reverse(ALL(flower[id]));
        while(v!=lca){
            flower[id].push_back(v);
            v=root[mate[v]];
            push(v);
            flower[id].push_back(v);
            v=root[par[v]];
        }
        set(id,id);
        for(auto& c:flower[id]){
            rep(i,1,m+1)if(!G[id][i].w or dist(G[c][i])<dist(G[id][i])){
                G[id][i]=G[c][i],G[i][id]=G[i][c];
            }
            rep(i,1,n+1)if(belong[c][i])belong[id][i]=c;
        }
        recalc(id);
    }
    void expand(int b){
        for(auto& c:flower[b])set(c,c);
        int x=belong[b][G[b][par[b]].u];
        isS[x]=2,par[x]=par[b];
        int pos=findeven(b,x);
        for(int i=0;i<pos;i+=2){
            int T=flower[b][i],S=flower[b][i+1];
            isS[S]=1,isS[T]=2;
            par[T]=G[S][T].u;
            slack[S]=slack[T]=0;
            push(S);
        }
        rep(i,pos+1,flower[b].size()){
            isS[flower[b][i]]=0;
            recalc(flower[b][i]);
        }
        flower[b].clear();
        root[b]=0;
    }
    bool path(const E& e){
        int u=root[e.u],v=root[e.v];
        if(!isS[v]){
            par[v]=e.u;
            isS[v]=2;
            int nu=root[mate[v]];
            slack[v]=slack[nu]=0;
            isS[nu]=1;
            push(nu);
        }
        else if(isS[v]==1){
            int lca=0,bu=u,bv=v;
            in++;
            while(bu){
                used[bu]=in;
                bu=root[mate[bu]];
                if(bu)bu=root[par[bu]];
            }
            while(bv){
                if(used[bv]==in){
                    lca=bv;
                    break;
                }
                bv=root[mate[bv]];
                if(bv)bv=root[par[bv]];
            }
            if(lca)make(u,v,lca);
            else{
                link(u,v),link(v,u);
                return true;
            }
        }
        return false;
    }
    bool augment(){
        isS=slack=par=vector<int>(n*2);
        que=queue<int>();
        rep(i,1,m+1)if(root[i]==i and !mate[i]){
            isS[i]=1;
            push(i);
        }
        if(que.empty())return false;
        for(;;){
            while(!que.empty()){
                int v=que.front();
                que.pop();
                rep(i,1,n+1)if(G[v][i].w and root[i]!=root[v]){
                    if(!dist(G[v][i])){
                        if(path(G[v][i]))return true;
                    }
                    else if(isS[root[i]]!=2)update(v,root[i]);
                }
            }
            ll delta=INF;
            rep(i,n+1,m+1)if(root[i]==i and isS[i]==2)chmin(delta,dual[i]/2);
            rep(i,1,m+1)if(root[i]==i and slack[i] and isS[i]!=2){
                if(!isS[i])chmin(delta,dist(G[slack[i]][i]));
                else chmin(delta,dist(G[slack[i]][i])/2);
            }
            rep(i,1,n+1){
                if(isS[root[i]]==1){
                    dual[i]-=delta;
                    if(dual[i]<=0)return false;
                }
                else if(isS[root[i]]==2)dual[i]+=delta;
            }
            rep(i,n+1,m+1)if(root[i]==i and isS[i]){
                if(isS[i]==1)dual[i]+=delta*2;
                else dual[i]-=delta*2;
            }
            rep(i,1,m+1)if(root[i]==i and slack[i] and root[slack[i]]!=i){
                if(dist(G[slack[i]][i])==0 and path(G[slack[i]][i]))return true;
            }
            rep(i,n+1,m+1)if(root[i]==i and isS[i]==2 and dual[i]==0)expand(i);
        }
    }
public:
    GeneralWeightedMatching(int _n):n(_n),m(n),in(0),G(n*2,vector<E>(n*2)),
        mate(n*2),root(n*2),used(n*2),flower(n*2),belong(n*2,vector<int>(n*2)),dual(n*2){
        rep(i,0,n+1){
            root[i]=i;
            belong[i][i]=i;
            if(i)dual[i]=INF;
            rep(j,0,n+1)G[i][j]=E{i,j,0};
        }
    }
    void add_edge(int u,int v,ll w){
        u++,v++;
        chmax(G[u][v].w,w*2);
        chmax(G[v][u].w,w*2);
    }
    vector<int> run(){
        while(augment());
        vector<int> res(n,-1);
        rep(i,1,n+1)if(mate[i])res[i-1]=mate[i]-1;
        return res;
    }
};

/**
 * @brief General Weighted Matching
*/

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int N, M;
    cin >> N >> M;
    vector<vector<int>> E(N);
    rep(i,0,M) {
        int K;
        cin >> K;
        while(K--) {
            int a;
            cin >> a;
            a--;
            E[a].push_back(i);
        }
    }
    vector<vector<int>> G(M, vector<int>(M, 0));
    int ANS = 0;
    rep(i,0,N) {
        if (E[i].size() == 1) {
            G[E[i][0]][E[i][0]] = 1;
        }
        else if (E[i].size() == 2) {
            G[E[i][0]][E[i][1]] = G[E[i][1]][E[i][0]] = 1;
        }
        else ANS++;
    }
    rep(i,0,M) if (G[i][i] == 1) ANS++;
    GeneralWeightedMatching GWM(M);
    rep(i,0,M) {
        rep(j,i+1,M) {
            if (G[i][i] == 0 && G[j][j] == 0 && G[i][j] == 1) GWM.add_edge(i,j,1);
        }
    }
    auto res = GWM.run();
    rep(i,0,M) if (res[i] > i) ANS++;
    cout << ANS << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 15904
final_rank: 3

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

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

/**
* @brief template
*/

class GeneralWeightedMatching{
    struct E{int u,v; ll w;};
    int n,m,in;
    vector<vector<E>> G;
    vector<int> mate,slack,root,par,isS,used;
    vector<vector<int>> flower,belong;
    vector<ll> dual;
    queue<int> que;
    
    ll dist(const E& e){return dual[e.u]+dual[e.v]-e.w;}
    void update(int u,int v){
        if(!slack[v] or dist(G[u][v])<dist(G[slack[v]][v]))slack[v]=u;
    }
    void recalc(int v){
        slack[v]=0;
        rep(i,1,n+1)if(G[i][v].w and root[i]!=v and isS[root[i]]==1)update(i,v);
    }
    void push(int v){
        if(v<=n)que.push(v);
        else for(auto& nxt:flower[v])push(nxt);
    }
    void set(int v,int rt){
        root[v]=rt;
        if(v>n)for(auto& nxt:flower[v])set(nxt,rt);
    }
    int findeven(int b,int v){
        int pos=find(ALL(flower[b]),v)-flower[b].begin();
        if(pos&1){
            reverse(flower[b].begin()+1,flower[b].end());
            pos=flower[b].size()-pos;
        }
        return pos;
    }
    void match(int u,int v){
        mate[u]=G[u][v].v;
        if(u>n){
            int x=belong[u][G[u][v].u];
            int pos=findeven(u,x);
            rep(i,0,pos)match(flower[u][i],flower[u][i^1]);
            match(x,v);
            rotate(flower[u].begin(),flower[u].begin()+pos,flower[u].end());
        }
    }
    void link(int u,int v){
        for(;;){
            int nv=root[mate[u]];
            match(u,v);
            if(!nv)break;
            v=nv,u=root[par[nv]];
            match(v,u);
        }
    }
    void make(int u,int v,int lca){
        int id=n+1;
        while(id<=m and root[id])id++;
        if(id>m)m++;
        flower[id].clear();
        rep(i,1,m+1)G[id][i].w=G[i][id].w=0;
        rep(i,1,n+1)belong[id][i]=0;
        isS[id]=1,dual[id]=0,mate[id]=mate[lca];
        while(u!=lca){
            flower[id].push_back(u);
            u=root[mate[u]];
            push(u);
            flower[id].push_back(u);
            u=root[par[u]];
        }
        flower[id].push_back(lca);
        reverse(ALL(flower[id]));
        while(v!=lca){
            flower[id].push_back(v);
            v=root[mate[v]];
            push(v);
            flower[id].push_back(v);
            v=root[par[v]];
        }
        set(id,id);
        for(auto& c:flower[id]){
            rep(i,1,m+1)if(!G[id][i].w or dist(G[c][i])<dist(G[id][i])){
                G[id][i]=G[c][i],G[i][id]=G[i][c];
            }
            rep(i,1,n+1)if(belong[c][i])belong[id][i]=c;
        }
        recalc(id);
    }
    void expand(int b){
        for(auto& c:flower[b])set(c,c);
        int x=belong[b][G[b][par[b]].u];
        isS[x]=2,par[x]=par[b];
        int pos=findeven(b,x);
        for(int i=0;i<pos;i+=2){
            int T=flower[b][i],S=flower[b][i+1];
            isS[S]=1,isS[T]=2;
            par[T]=G[S][T].u;
            slack[S]=slack[T]=0;
            push(S);
        }
        rep(i,pos+1,flower[b].size()){
            isS[flower[b][i]]=0;
            recalc(flower[b][i]);
        }
        flower[b].clear();
        root[b]=0;
    }
    bool path(const E& e){
        int u=root[e.u],v=root[e.v];
        if(!isS[v]){
            par[v]=e.u;
            isS[v]=2;
            int nu=root[mate[v]];
            slack[v]=slack[nu]=0;
            isS[nu]=1;
            push(nu);
        }
        else if(isS[v]==1){
            int lca=0,bu=u,bv=v;
            in++;
            while(bu){
                used[bu]=in;
                bu=root[mate[bu]];
                if(bu)bu=root[par[bu]];
            }
            while(bv){
                if(used[bv]==in){
                    lca=bv;
                    break;
                }
                bv=root[mate[bv]];
                if(bv)bv=root[par[bv]];
            }
            if(lca)make(u,v,lca);
            else{
                link(u,v),link(v,u);
                return true;
            }
        }
        return false;
    }
    bool augment(){
        isS=slack=par=vector<int>(n*2);
        que=queue<int>();
        rep(i,1,m+1)if(root[i]==i and !mate[i]){
            isS[i]=1;
            push(i);
        }
        if(que.empty())return false;
        for(;;){
            while(!que.empty()){
                int v=que.front();
                que.pop();
                rep(i,1,n+1)if(G[v][i].w and root[i]!=root[v]){
                    if(!dist(G[v][i])){
                        if(path(G[v][i]))return true;
                    }
                    else if(isS[root[i]]!=2)update(v,root[i]);
                }
            }
            ll delta=INF;
            rep(i,n+1,m+1)if(root[i]==i and isS[i]==2)chmin(delta,dual[i]/2);
            rep(i,1,m+1)if(root[i]==i and slack[i] and isS[i]!=2){
                if(!isS[i])chmin(delta,dist(G[slack[i]][i]));
                else chmin(delta,dist(G[slack[i]][i])/2);
            }
            rep(i,1,n+1){
                if(isS[root[i]]==1){
                    dual[i]-=delta;
                    if(dual[i]<=0)return false;
                }
                else if(isS[root[i]]==2)dual[i]+=delta;
            }
            rep(i,n+1,m+1)if(root[i]==i and isS[i]){
                if(isS[i]==1)dual[i]+=delta*2;
                else dual[i]-=delta*2;
            }
            rep(i,1,m+1)if(root[i]==i and slack[i] and root[slack[i]]!=i){
                if(dist(G[slack[i]][i])==0 and path(G[slack[i]][i]))return true;
            }
            rep(i,n+1,m+1)if(root[i]==i and isS[i]==2 and dual[i]==0)expand(i);
        }
    }
public:
    GeneralWeightedMatching(int _n):n(_n),m(n),in(0),G(n*2,vector<E>(n*2)),
        mate(n*2),root(n*2),used(n*2),flower(n*2),belong(n*2,vector<int>(n*2)),dual(n*2){
        rep(i,0,n+1){
            root[i]=i;
            belong[i][i]=i;
            if(i)dual[i]=INF;
            rep(j,0,n+1)G[i][j]=E{i,j,0};
        }
    }
    void add_edge(int u,int v,ll w){
        u++,v++;
        chmax(G[u][v].w,w*2);
        chmax(G[v][u].w,w*2);
    }
    vector<int> run(){
        while(augment());
        vector<int> res(n,-1);
        rep(i,1,n+1)if(mate[i])res[i-1]=mate[i]-1;
        return res;
    }
};

/**
 * @brief General Weighted Matching
*/

int main() {
    cin.tie(0);
    ios_base::sync_with_stdio(false);
    int N, M;
    cin >> N >> M;
    vector<vector<int>> E(N);
    rep(i,0,M) {
        int K;
        cin >> K;
        while(K--) {
            int a;
            cin >> a;
            a--;
            E[a].push_back(i);
        }
    }
    vector<vector<int>> G(M, vector<int>(M, 0));
    rep(i,0,N) {
        if (E[i].size() == 1) {
            G[E[i][0]][E[i][0]] = 1;
        }
        if (E[i].size() == 2) {
            G[E[i][0]][E[i][1]] = G[E[i][1]][E[i][0]] = 1;
        }
    }
    int ANS = 0;
    rep(i,0,M) if (G[i][i] == 1) ANS++;
    GeneralWeightedMatching GWM(M);
    rep(i,0,M) {
        rep(j,i+1,M) {
            if (G[i][i] == 0 && G[j][j] == 0 && G[i][j] == 1) GWM.add_edge(i,j,1);
        }
    }
    auto res = GWM.run();
    rep(i,0,M) if (res[i] > i) ANS++;
    cout << ANS << endl;
}
accuracy: 0.06382978723404255
time_ms: 10
memory_kb: 15936
final_rank: 18

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

using ll = long long;

void solve() {
  ll N, M; cin >> N >> M;
  vector< vector<ll> > ops(M);
  vector< vector<ll> > op_id(N);
  for (int i = 0; i < M; ++i) {
    ll k; cin >> k;
    for (int j = 0; j < k; ++j) {
      ll v; cin >> v;
      v--;
      ops[i].emplace_back(v);
      op_id[v].emplace_back(i);
    }
  }
  
  vector<ll> can(N, 0);
  vector<ll> used(M, 0);
  
  // use #0
  for (int v = 0; v < N; ++v) {
    if (op_id[v].size() == 0) can[v] = 1;
  }
  
  // use #1
  for (int i = 0; i < M; ++i) {
    ll u = -1;
    for (auto v : ops[i]) {
      if (op_id[v].size() == 1) u = v;
    }
    if (u != -1) {
      used[i] = 1;
      for (auto v : ops[i]) {
        can[v] = (u == v ? 1 : -1);
      }
    }
  }
  
  // use #2
  vector<vector<ll>> graph(N+M);
  ll r = -1;
  for (int i = 0; i < M; ++i) {
    if (used[i]) continue;
    for (auto v : ops[i]) {
      if (can[v] == -1) continue;
      graph[N+i].emplace_back(v);
      graph[v].emplace_back(N+i);
      r = v;
    }
  }
  if (r != -1) {
    const ll INF = 1e9;
    vector<ll> dist(N+M, INF);
    queue<ll> que;
    que.emplace(r);
    dist[r] = 0;
    vector<ll> vec;
    
    while (que.size()) {
      ll v = que.front();
      que.pop();
      if (v < N) vec.emplace_back(v);
      
      for (auto nv : graph[v]) {
        if (dist[nv] == INF) {
          dist[nv] = dist[v] + 1;
          que.emplace(nv);
        }
      }
    }
    
    for (auto v : vec) {
      bool flg = true;
      for (auto i : op_id[v]) {
        if (used[i]) flg = false;
      }
      if (flg) {
        can[v] = 1;
        for (auto i : op_id[v]) {
          used[i] = 1;
        }
      }
      
    }
    
  }
  
  ll res = 0;
  for (int v = 0; v < N; ++v) {
    if (can[v] > 0) res++;
  }
  cout << res << endl;
  
  return;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  
  solve();
  
  return 0;
}
accuracy: 0.0851063829787234
time_ms: 10
memory_kb: 21936
final_rank: 17

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

#define ll long long
#define elif else if
#define vi vector<int>
#define vll vector<ll>
#define vvi vector<vi>
#define rep(i, n) for (int i = 0; i < (n); i++)
#define rep2(i, l, r) for (int i = l; i < (r); i++)

vector<pair<int, int>> Matching_on_General_Graph(int N, vector<pair<int, int>> &edges)
{
  // edge は単純無向グラフ

  mt19937 rnd;
  vector<int> used(N + 1), mt(N + 1);
  vector<vector<int>> g(N + 1);
  for (auto [u, v] : edges)
  {
    if (u != v)
    {
      g[u + 1].push_back(v + 1);
      g[v + 1].push_back(u + 1);
    }
  }

  int T;

  auto dfs = [&](auto dfs, int v) -> bool
  {
    used[v] = T;
    shuffle(g[v].begin(), g[v].end(), rnd);
    for (auto u : g[v])
    {
      int w = mt[u];
      if (used[w] < T)
      {
        mt[v] = u, mt[u] = v, mt[w] = 0;
        if (!w || dfs(dfs, w))
          return true;
        mt[u] = w, mt[w] = u, mt[v] = 0;
      }
    }
    return false;
  };

  int C = 0;
  for (int i = 0; i < 10; i++)
  {
    used.assign(N + 1, 0);
    for (T = 1; T <= N; ++T)
    {
      if (!mt[T])
      {
        C += (int)dfs(dfs, T);
      }
    }
  }

  vector<pair<int, int>> matching;
  for (int i = 1; i <= N; i++)
  {
    if (mt[i] > 0 && mt[i] < i)
    {
      matching.push_back({mt[i] - 1,
                          i - 1});
    }
  }
  return matching;
}

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

  int n, m;
  cin >> n >> m;
  vvi res(n);
  rep(i, m)
  {
    int k;
    cin >> k;
    rep(j, k)
    {
      int v;
      cin >> v;
      v--;
      res[v].push_back(i);
    }
  }
  int ans = 0;
  vector<int> only(m, 0);
  vector<pair<int, int>> edge;
  rep(i, n)
  {
    if (res[i].size() == 0)
      ans++;
    elif (res[i].size() == 1)
    {
      int x = res[i][0];
      if (only[x] == 0)
      {
        only[x] = 1;
        ans++;
      }
    }
  }

  rep(i, n)
  {
    if (res[i].size() == 2)
    {
      int x = res[i][0];
      int y = res[i][1];
      if (only[x] == 0 && only[y] == 0)
      {
        edge.push_back({x, y});
      }
    }
  }
  cout << ans + Matching_on_General_Graph(m, edge).size() << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 10512
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define db double
#define pii pair<int,int>
#define pli pair<ll,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
#define ti3 tuple<int,int,int>
#define int128 __int128_t
#define pii128 pair<int128,int128>
const int inf = 1 << 30;
const ll linf = (ll)4e18 + 10;;
const db EPS = 1e-10;
const db pi = acos(-1);
template<class T> bool chmin(T& x, T y){
    if(x > y) {
        x = y;
        return true;
    } else return false;
}
template<class T> bool chmax(T& x, T y){
    if(x < y) {
        x = y;
        return true;
    } else return false;
}

// overload macro
#define CAT( A, B ) A ## B
#define SELECT( NAME, NUM ) CAT( NAME, NUM )

#define GET_COUNT( _1, _2, _3, _4, _5, _6 /* ad nauseam */, COUNT, ... ) COUNT
#define VA_SIZE( ... ) GET_COUNT( __VA_ARGS__, 6, 5, 4, 3, 2, 1 )

#define VA_SELECT( NAME, ... ) SELECT( NAME, VA_SIZE(__VA_ARGS__) )(__VA_ARGS__)

// rep(overload)
#define rep( ... ) VA_SELECT(rep, __VA_ARGS__)
#define rep2(i, n) for (int i = 0; i < int(n); i++)
#define rep3(i, a, b) for (int i = a; i < int(b); i++)
#define rep4(i, a, b, c) for (int i = a; i < int(b); i += c)

// repll(overload)
#define repll( ... ) VA_SELECT(repll, __VA_ARGS__)
#define repll2(i, n) for (ll i = 0; i < (ll)(n); i++)
#define repll3(i, a, b) for (ll i = a; i < (ll)(b); i++)
#define repll4(i, a, b, c) for (ll i = a; i < (ll)(b); i += c)

// rrep(overload)
#define rrep( ... ) VA_SELECT(rrep, __VA_ARGS__)
#define rrep2(i, n) for (int i = n - 1; i >= 0; i--)
#define rrep3(i, a, b) for (int i = (b) - 1; i >= a; i--)
#define rrep4(i, a, b, c) for (int i = (b) - 1; i >= a; i -= c)

// rrepll(overload)
#define rrepll( ... ) VA_SELECT(rrepll, __VA_ARGS__)
#define rrepll2(i, n) for (ll i = (ll)(n) - 1; i >= 0ll; i--)
#define rrepll3(i, a, b) for (ll i = (b) - 1; i >= (ll)(a); i--)
#define rrepll4(i, a, b, c) for (ll i = (b) - 1; i >= (ll)(a); i -= c)

// for_earh
#define fore(e, v) for (auto&& e : v)

// vector
#define all(v) v.begin(), v.end()
#define rall(v) v.rbegin(), v.rend()

class GeneralMatching {
   public:
    GeneralMatching() = default;
    explicit GeneralMatching(int n)
        : n(n), m(n + n / 2), G(m, std::vector<bool>(m)), mate(m, -1) {}

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

    std::vector<std::pair<int, int>> max_matching() {
        // par: parent in the alternating forest
        // dep: 0 if even, 1 if odd, -1 if not in the forest
        // comp: id of the comp in the forest
        // alive: whether the blossom/vertex is alive
        // blossom: members of the blossom
        std::vector<int> par(m), dep(m), comp(m);
        std::vector<bool> alive(m, true);
        std::vector<std::vector<int>> blossom(m);

        auto get_ancestors = [&](int v) {
            std::vector<int> ret;
            while (v != -1) {
                ret.push_back(v);
                v = par[v];
            }
            return ret;
        };

        auto flip_to_root = [&](int v) {
            mate[v] = -1;
            int w = par[v];
            while (w != -1) {
                int p = par[w];
                mate[w] = p;
                mate[p] = w;
                w = par[p];
            }
        };

        for (int ans = 0;; ++ans) {
            fill(all(par), -1);
            fill(all(dep), -1);
            fill(all(comp), -1);
            bool augment = false;
            int c = n;  // n + number of blossoms

            // seed
            std::queue<int> que;
            for (int v = 0; v < n; ++v) {
                if (mate[v] == -1) {
                    que.push(v);
                    dep[v] = 0;
                    comp[v] = v;
                }
            }

            // repeat until an augmenting path is found
            while (!que.empty() && !augment) {
                int v = que.front();
                que.pop();
                if (!alive[v]) continue;
                for (int u = 0; u < c; ++u) {
                    if (!G[v][u] || !alive[u] || dep[u] == 1) continue;
                    if (dep[u] == -1) {
                        // grow
                        int w = mate[u];
                        par[u] = v;
                        par[w] = u;
                        dep[u] = 1;
                        dep[w] = 0;
                        comp[u] = comp[w] = comp[v];
                        que.push(w);
                    } else if (comp[v] == comp[u]) {
                        // shrink

                        // build the blossom
                        auto av = get_ancestors(v);
                        auto au = get_ancestors(u);
                        int w;  // lca
                        while (!av.empty() && !au.empty() &&
                               av.back() == au.back()) {
                            w = av.back();
                            av.pop_back();
                            au.pop_back();
                        }
                        blossom[c] = std::move(av);
                        blossom[c].push_back(w);
                        reverse(all(blossom[c]));
                        // std::ranges::move(au, std::back_inserter(blossom[c]));
                        move(all(au), back_inserter(blossom[c]));

                        // contract
                        if (par[w] != -1) mate[par[w]] = c;
                        par[c] = mate[c] = par[w];
                        dep[c] = 0;
                        comp[c] = comp[w];
                        for (int x : blossom[c]) {
                            alive[x] = false;
                            mate[x] = -1;
                        }
                        for (int x : blossom[c]) {
                            for (int y = 0; y < c; ++y) {
                                if (G[x][y] && alive[y]) {
                                    G[y][c] = G[c][y] = true;
                                    if (par[y] == x) par[y] = c;
                                }
                            }
                        }

                        que.push(c);
                        ++c;
                        break;
                    } else {
                        // augment
                        augment = true;
                        flip_to_root(v);
                        flip_to_root(u);
                        mate[v] = u;
                        mate[u] = v;
                        break;
                    }
                }
            }

            // restore blossoms
            while (c > n) {
                --c;
                int b = blossom[c].size();

                // select the base
                int base_idx;
                if (mate[c] == -1) {
                    base_idx = 0;
                } else {
                    base_idx = -1;
                    for (int i = 0; i < b; ++i) {
                        int x = blossom[c][i];
                        int y = mate[c];
                        if (G[x][y]) {
                            base_idx = i;
                            mate[c] = -1;
                            mate[y] = x;
                            mate[x] = y;
                            break;
                        }
                    }
                    assert(base_idx != -1);
                }

                // restore matches
                for (int i = 1; i < b; i += 2) {
                    int u = blossom[c][(base_idx + i) % b];
                    int v = blossom[c][(base_idx + i + 1) % b];
                    mate[u] = v;
                    mate[v] = u;
                }

                for (int x : blossom[c]) alive[x] = true;
                for (int y = 0; y < c; ++y) G[c][y] = G[y][c] = false;
                blossom[c].clear();
            }

            if (!augment) {
                std::vector<std::pair<int, int>> matches;
                for (int i = 0; i < n; ++i) {
                    if (i < mate[i]) {
                        matches.emplace_back(i, mate[i]);
                    }
                }
                return matches;
            }
        }
    }

   private:
    int n, m;  // m: maximum number of vertices + blossoms
    std::vector<std::vector<bool>> G;  // adjacency matrix
    std::vector<int> mate;             // -1 if not matched
};

int N, M, K;
bool used[310];
vector<int> S[100010];
int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(20);
    cin >> N >> M;
    rep (i, M) {
        cin >> K;
        int v;
        rep (j, K) {
            cin >> v;
            v--;
            S[v].push_back(i);
        }
    }

    int cnt = 0;
    rep (i, N) {
        if (S[i].size() == 2) continue;
        if (S[i].size() == 1) {
            if (used[S[i][0]]) continue;
            cnt++;
            used[S[i][0]] = true;
        } else {
            cnt++;
        }
    }

    GeneralMatching gm(M);
    rep (i, N) {
        if (S[i].size() < 2) continue;
        if (!used[S[i][0]] && !used[S[i][1]]) {
            gm.add_edge(S[i][0], S[i][1]);
        }
    }

    cout << cnt + gm.max_matching().size() << '\n';
}
accuracy: 1
time_ms: 10
memory_kb: 8944
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <class T>
using V = vector<T>;

#define foa(s, v) for(auto &s : v)
#define all(v)    v.begin(), v.end()
#define sz(v)     int(v.size())
#define rep(i, n) for(int i = 0; i < int(n); i++)

template <class T>
bool chmin(T &a, T b) { return a > b ? a = b, 1 : 0; }
template <class T>
bool chmax(T &a, T b) { return a < b ? a = b, 1 : 0; }

string strmax(string &a, string &b) {
	if(a[0] == '-') return b;
	if(b[0] == '-') return a;
	if(sz(a) < sz(b)) return b;
	if(sz(a) > sz(b)) return a;
	return max(a, b);
}

const ll mod = 1000000007;

ll modpow(ll b, ll e) {
	ll ans = 1;
	for(; e; b = b * b % mod, e /= 2)
		if(e & 1) ans = ans * b % mod;
	return ans;
}

int matInv(V<V<ll>> &A) {
	int n = sz(A);
	V<int> col(n);
	V<V<ll>> tmp(n, V<ll>(n));
	rep(i, n) tmp[i][i] = 1, col[i] = i;
	rep(i, n) {
		int r = i, c = i;
		for(int j = i; j < n; j++) {
			for(int k = i; k < n; k++) {
				if(A[j][k]) {
					r = j;
					c = k;
					goto found;
				}
			}
		}
		return i;
	found:
		A[i].swap(A[r]);
		tmp[i].swap(tmp[r]);
		rep(j, n) swap(A[j][i], A[j][c]), swap(tmp[j][i], tmp[j][c]);
		swap(col[i], col[c]);
		ll v = modpow(A[i][i], mod - 2);
		for(int j = i + 1; j < n; j++) {
			ll f = A[j][i] * v % mod;
			A[j][i] = 0;
			for(int k = i + 1; k < n; k++) A[j][k] = (A[j][k] - f * A[i][k]) % mod;
			rep(k, n) tmp[j][k] = (tmp[j][k] - f * tmp[i][k]) % mod;
		}
		for(int j = i + 1; j < n; j++) A[i][j] = A[i][j] * v % mod;
		rep(j, n) tmp[i][j] = tmp[i][j] * v % mod;
		A[i][i] = 1;
	}
	for(int i = n - 1; i > 0; --i) rep(j, i) {
			ll v = A[j][i];
			rep(k, n) tmp[j][k] = (tmp[j][k] - v * tmp[i][k]) % mod;
		}
	rep(i, n) rep(j, n)
	    A[col[i]][col[j]] = tmp[i][j] % mod + (tmp[i][j] < 0 ? mod : 0);
	return n;
}

vector<pair<int, int>> general_matching(int N, vector<pair<int, int>> &ed) {
	if(sz(ed) == 0) return {};
	V<V<ll>> mat(N, V<ll>(N)), A;
	for(pair<int, int> pa : ed) {
		int a = pa.first, b = pa.second, r = rand() % mod;
		mat[a][b] = r, mat[b][a] = (mod - r) % mod;
	}
	int r = matInv(A = mat), M = 2 * N - r, fi, fj;
	assert(r % 2 == 0);
	if(M != N) do {
			mat.resize(M, V<ll>(M));
			rep(i, N) {
				mat[i].resize(M);
				for(int j = N; j < M; j++) {
					int r = rand() % mod;
					mat[i][j] = r, mat[j][i] = (mod - r) % mod;
				}
			}
		} while(matInv(A = mat) != M);

	V<int> has(M, 1);
	V<pair<int, int>> ret;
	rep(it, M / 2) {
		rep(i, M) if(has[i]) for(int j = i + 1; j < M; j++) if(A[i][j] && mat[i][j]) {
			fi = i;
			fj = j;
			goto done;
		}
		assert(0);
	done:
		if(fj < N) ret.emplace_back(fi, fj);
		has[fi] = has[fj] = 0;
		rep(sw, 2) {
			ll a = modpow(A[fi][fj], mod - 2);
			rep(i, M) if(has[i] && A[i][fj]) {
				ll b = A[i][fj] * a % mod;
				rep(j, M) A[i][j] = (A[i][j] - A[fi][j] * b) % mod;
			}
			swap(fi, fj);
		}
	}
	return ret;
}

void solve() {
	int n, m;
	cin >> n >> m;
	vector<V<int>> cnt(n);
	rep(i, m) {
		int k;
		cin >> k;
		rep(j, k) {
			int v;
			cin >> v;
			cnt[--v].push_back(i);
		}
	}
	int res = 0;
	vector<int> out(m);
	// m 頂点 各 i cnt[i][0] - cnt[i][1]
	rep(i, n) {
		if(sz(cnt[i]) == 0)
			res++;
		else if(sz(cnt[i]) == 1) {
			if(!out[cnt[i][0]]) {
				res++;
				out[cnt[i][0]] = 1;
			}
		}
	}
	set<pair<int, int>> st;
	rep(i, n) {
		if(sz(cnt[i]) == 2) {
			auto u = cnt[i][0], v = cnt[i][1];
			if(out[u] or out[v]) continue;
			if(u > v) swap(u, v);
			st.insert({u, v});
		}
	}
	vector<pair<int, int>> ed;
	for(auto v : st) ed.push_back(v);
	cout << sz(general_matching(m, ed)) + res << endl;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	solve();
}
accuracy: 1
time_ms: 80
memory_kb: 10636
final_rank: 6

code_snippet: #include <bits/stdc++.h>
#define ll long long
#define INF 1000000005
#define MOD 1000000007
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
#define each(a,b) for(auto& (a): (b))
#define all(v) (v).begin(),(v).end()
#define len(v) (int)(v).size()
#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define fi first
#define se second
#define pb push_back
#define show(x) cout<<#x<<" = "<<(x)<<endl
#define sar(a,n) cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl

using namespace std;

template<typename S,typename T>auto&operator<<(ostream&o,pair<S,T>p){return o<<"{"<<p.fi<<","<<p.se<<"}";}
template<typename T>auto&operator<<(ostream&o,set<T>s){for(auto&e:s)o<<e<<" ";return o;}
template<typename S,typename T,typename U>
auto&operator<<(ostream&o,priority_queue<S,T,U>q){while(!q.empty())o<<q.top()<<" ",q.pop();return o;}
template<typename K,typename T>auto&operator<<(ostream&o,map<K,T>m){for(auto&e:m)o<<e<<" ";return o;}
template<typename T>auto&operator<<(ostream&o,vector<T>v){for(auto&e:v)o<<e<<" ";return o;}
void ashow(){cout<<endl;}template<typename T,typename...A>void ashow(T t,A...a){cout<<t<<" ";ashow(a...);}

typedef pair<int,int> P;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef vector<P> vp;
typedef vector<double> vd;
typedef vector<string> vs;

const int MAX_N = 100005;

template <uint mod>
class ModInt {
private:
    uint v;
    static uint norm(const uint& x){ return x < mod ? x : x - mod; }
	static ModInt make(const uint& x){ ModInt m; return m.v = x, m; }
    static ModInt inv(const ModInt& x){ return make(inverse(x.v, mod)); }
    static uint inverse(int a, int m){
        int u[] = {a, 1, 0}, v[] = {m, 0, 1}, t;
        while(*v){
            t = *u / *v;
            swap(u[0] -= t * v[0], v[0]), swap(u[1] -= t * v[1], v[1]), swap(u[2] -= t * v[2], v[2]);
        }
        return (u[1] % m + m) % m;
    }

public:
    ModInt() : v{0}{}
    ModInt(const ll val) : v{norm(val % mod + mod)} {}
    ModInt(const ModInt<mod>& n) : v{n()} {}
	explicit operator bool() const noexcept { return v != 0; }
    bool operator!() const noexcept { return !static_cast<bool>(*this); }
    ModInt& operator=(const ModInt& n){ return v = n(), (*this); }
    ModInt& operator=(const ll val){ return v = norm(val % mod + mod), (*this); }
    ModInt operator+() const { return *this; }
    ModInt operator-() const { return v == 0 ? 0 : mod - v; }
    ModInt operator+(const ModInt& val) const { return make(norm(v + val())); }
    ModInt operator-(const ModInt& val) const { return make(norm(v + mod - val())); }
    ModInt operator*(const ModInt& val) const { return make((ll)v * val() % mod); }
    ModInt operator/(const ModInt& val) const { return *this * inv(val); }
    ModInt& operator+=(const ModInt& val){ return *this = *this + val; }
    ModInt& operator-=(const ModInt& val){ return *this = *this - val; }
    ModInt& operator*=(const ModInt& val){ return *this = *this * val; }
    ModInt& operator/=(const ModInt& val){ return *this = *this / val; }
    ModInt operator+(const ll val) const { return ModInt{v + val}; }
    ModInt operator-(const ll val) const { return ModInt{v - val}; }
    ModInt operator*(const ll val) const { return ModInt{(ll)v * (val % mod)}; }
    ModInt operator/(const ll val) const { return ModInt{(ll)v * inv(val)}; }
    ModInt& operator+=(const ll val){ return *this = *this + val; }
    ModInt& operator-=(const ll val){ return *this = *this - val; }
    ModInt& operator*=(const ll val){ return *this = *this * val; }
    ModInt& operator/=(const ll val){ return *this = *this / val; }
    bool operator==(const ModInt& val) const { return v == val.v; }
    bool operator!=(const ModInt& val) const { return !(*this == val); }
    bool operator==(const ll val) const { return v == norm(val % mod + mod); }
    bool operator!=(const ll val) const { return !(*this == val); }
    uint operator()() const { return v; }
    friend ModInt operator+(const ll val, const ModInt& n) { return n + val; }
    friend ModInt operator-(const ll val, const ModInt& n) { return ModInt{val - n()}; }
    friend ModInt operator*(const ll val, const ModInt& n) { return n * val; }
    friend ModInt operator/(const ll val, const ModInt& n) { return ModInt{val} / n; }
    friend bool operator==(const ll val, const ModInt& n) { return n == val; }
    friend bool operator!=(const ll val, const ModInt& n) { return !(val == n); }
    friend istream& operator>>(istream& is, ModInt& n){
        uint v;
        return is >> v, n = v, is;
    }
    friend ostream& operator<<(ostream& os, const ModInt& n){ return (os << n()); }
    friend ModInt power(ModInt x, ll n){
        ModInt ans = 1;
        while(n){
            if(n & 1) ans *= x;
            x *= x, n >>= 1;
        }
        return ans;
    }
};

template<typename T> class mat : public vector<vector<T> > {
private:
    int r, c;    //行,列
public:
    inline int row() const { return r; }
    inline int column() const { return c; }
    mat(const int n) : mat(n, n, 0){}
    mat(const int n, const int m, T val = 0)
        : vector<vector<T> >(n, vector<T>(m, val)), r{n}, c{m}{}
    mat operator+(const mat& another) const {
        mat<T> X(r, c);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < c; j++){
                X[i][j] = (*this)[i][j] + another[i][j];
            }
        }
        return X;
    }
    mat operator-(const mat& another) const {
        mat<T> X(r,c);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < c; j++){
                X[i][j] = (*this)[i][j] - another[i][j];
            }
        }
        return X;
    }
    mat operator*(const mat& another) const {
        mat<T> X(r, another.c);
        for(int i = 0; i < r; i++){
            for(int k = 0; k < c; k++){
                if(!(*this)[i][k]) continue;
                for(int j = 0; j < (another.c); j++){
                    X[i][j] += (*this)[i][k] * another[k][j];
                }
            }
        }
        return X;
    }
    vector<int> rank(){
        mat<T> X(r, c);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < c; j++){
                X[i][j] = (*this)[i][j];
            }
        }
        vector<int> index;
        int res = 0;
        for(int i = 0; i < c; i++){
            if(res == r) break;
            if(!X[res][i]){
                int pivot = res + 1;
                for(; pivot < r; pivot++){
                    if(X[pivot][i]){
                        swap(X[res], X[pivot]);
                        break;
                    }
                }
                if(pivot == r) continue;
            }
            const T p = (T)1 / X[res][i];
            for(int j = i + 1; j < c; j++){ X[res][j] *= p; }
            for(int j = res + 1; j < r; j++){
                if(!X[j][i]) continue;
                for(int k = i + 1; k < c; k++){
                    X[j][k] -= X[res][k] * X[j][i];
                }
            }
            index.push_back(i), ++res;
        }
        return index;
    }
    bool det_zero() const {
        mat<T> X(r);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < c; j++){
                X[i][j] = (*this)[i][j];
            }
        }
        for(int i = 0; i < c; i++){
            if(!X[i][i]){
                int pivot = i + 1;
                for(; pivot < r; pivot++){
                    if(X[pivot][i]){
                        swap(X[i], X[pivot]);
                        break;
                    }
                }
                if(pivot == r) return true;
            }
            const T p = (T)1 / X[i][i];
            for(int j = i + 1; j < c; j++){ X[i][j] *= p; }
            for(int j = i + 1; j < r; j++){
                if(!X[j][i]) continue;
                for(int k = i + 1; k < c; k++){
                    X[j][k] -= X[i][k] * X[j][i];
                }
            }
        }
        return false;
    }
    mat inverse() const {
        mat X(r, 2*r);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < r; j++){
                X[i][j] = (*this)[i][j];
            }
        }
        for(int i = 0; i < r; i++){
            X[i][r+i] = 1;
        }
        for(int i = 0; i < r; i++){
            if(!X[i][i]){
                int pivot = i + 1;
                for(; pivot < r; pivot++){
                    if(X[pivot][i]){
                        swap(X[i],X[pivot]);
                        break;
                    }
                }
                assert(pivot < r);
            }
            const T p = (T)1 / X[i][i];
            for(int j = i + 1; j < 2*r; j++){ X[i][j] *= p; }
            for(int j = 0; j < r; j++){
                if(i == j || !X[j][i]) continue;
                for(int k = i + 1; k < 2*r; k++){
                    X[j][k] -= X[i][k] * X[j][i];
                }
            }
        }
        mat res(r, r);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < r; j++){
                res[i][j] = X[i][r+j];
            }
        }
        return res;
    }
};

class Matching {
private:
    const int V;
    vector<pair<int, int> > es;
    vector<int> index, cnt;
    random_device rnd;
	mt19937 mt;
    uniform_int_distribution<> randval;
    static constexpr int LOOP = 1;
    static constexpr uint mod = 1000000007;
    mat<ModInt<mod> > inverse_22(const int id, const mat<ModInt<mod> >& invT){
        ModInt<mod> invdev = (ModInt<mod>)1 / (invT[0][0]*invT[id][id] - invT[0][id]*invT[id][0]);
        mat<ModInt<mod> > invN_3n_3n(2, 2);
        invN_3n_3n[0][0] = invT[id][id] * invdev, invN_3n_3n[0][1] = -invT[0][id] * invdev;
        invN_3n_3n[1][0] = -invT[id][0] * invdev, invN_3n_3n[1][1] = invT[0][0] * invdev;
        return invN_3n_3n;
    }
    void schur_complement(const int id, mat<ModInt<mod> >& invT){
        int sz = invT.row(), x = 0;
        mat<ModInt<mod> >N_12_12(sz-2), N_12_3n(sz-2, 2), N_3n_12(2, sz-2);
        for(int i = 1; i < sz; i++){
            if(i == id) continue;
            int y = 0;
            for(int j = 1; j < sz; j++){
                if(j == id) continue;
                N_12_12[x][y] = invT[i][j];
                N_3n_12[0][y] = invT[0][j], N_3n_12[1][y++] = invT[id][j];
            }
            N_12_3n[x][0] = invT[i][0], N_12_3n[x++][1] = invT[i][id];
        }
        invT = N_12_12 - N_12_3n * inverse_22(id, invT) * N_3n_12;
    }
    void find_matching(const mat<ModInt<mod> >& T){
        int sz = T.row();
        mat<ModInt<mod> > invT = T.inverse();
        vector<int> vset(sz); iota(vset.begin(), vset.end(), 0);
        for(int i = sz; i > 0; i -= 2){
            for(int j = 1; j < i; j++){
                if(invT[0][j] && T[vset[0]][vset[j]]){
                    ans.emplace_back(index[vset[0]], index[vset[j]]);
                    vset.erase(vset.begin()), vset.erase(vset.begin() + j - 1);
                    schur_complement(j, invT);
                    break;
                }
            }
        }
    }

public:
    vector<pair<int, int> > ans;

    Matching(const int node_size)
        : V(node_size), cnt(V + 1, 0), mt(rnd()), randval(1, mod - 1){}
    void add_edge(const int u, const int v){ es.emplace_back(u, v); }
    bool perfect_matchching(){
        for(int i = 0; i < LOOP; i++){
            mat<ModInt<mod> > A(V);
            for(auto e : es){
                int r = randval(mt);
                A[e.first][e.second] = r, A[e.second][e.first] = -r;
            }
            if(!A.det_zero()) return true;
        }
        return false;
    }
    int maximum_matchching(){
        for(int i = 0; i < LOOP; i++){
            mat<ModInt<mod> > A(V);
            for(auto e : es){
                int r = randval(mt);
                A[e.first][e.second] = r, A[e.second][e.first] = -r;
            }
            vector<int> res = A.rank();
            ++cnt[res.size()];
            if((size_t)(max_element(cnt.begin(), cnt.end()) - cnt.begin()) == res.size()){
                index = move(res);
            }
        }
        return (int)(max_element(cnt.begin(), cnt.end()) - cnt.begin()) / 2;
    }
    int find_maximum_matching(){
        const int sz = maximum_matchching();
        vector<pair<int, int> > ans_tmp;
        vector<int> unzip(V, -1);
        for(int i = 0; i < 2 * sz; ++i) unzip[index[i]] = i;
        for(int i = 0; i < LOOP; i++){
            mat<ModInt<mod> > A(2 * sz);
            for(auto e : es){
                const int u = unzip[e.first], v = unzip[e.second];
                if(u < 0 || v < 0) continue;
                int r = randval(mt);
                A[u][v] = r, A[v][u] = -r;
            }
            if(!A.det_zero()){
                find_matching(A);
                break;
            }
        }
        return sz;
    }
};

int main()
{
    int n,m;
    cin >> n >> m;

    vector<set<int>> vs(n);
    vector<set<int>> containVs(m);
    for(int i = 0; m > i; i++) {
        int k;
        cin >> k;
        for(int j = 0; k > j; j++) {
            int v;
            cin >> v;
            v--;

            vs[v].insert(i);
            containVs[i].insert(v);
        }
    }

    int untouchcount = 0;
    queue<int> que;
    for(int i = 0; n > i; i++) {
        if(vs[i].size() == 1) {
            que.push(i);
        }
        if(vs[i].empty()) {
            untouchcount++;
        }
    }

    int erasedControls = 0;
    while(!que.empty()) {
        int c = que.front();
        que.pop();
        if(vs[c].size() == 0) continue;

        int ct = *(vs[c].begin());
        erasedControls++;
        for(int v : containVs[ct]) {
            vs[v].clear();
        }
    }

    Matching mt(m);
    set<pair<int,int>> al;
    for(int i = 0; n > i; i++) {
        if(vs[i].size() == 2) {
            int from = *(vs[i].begin()), to = *(vs[i].rbegin());
            if(al.count(make_pair(from, to)) == 0) {
                mt.add_edge(from, to);
                al.insert(make_pair(from, to));
            }
        }
    }

    mt.find_maximum_matching();
    cout << mt.ans.size() + untouchcount + erasedControls<< endl;


    return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 28224
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define ll long long
#define INF 1000000005
#define MOD 1000000007
#define EPS 1e-10
#define rep(i,n) for(int i=0;i<(int)(n);++i)
#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
#define each(a,b) for(auto& (a): (b))
#define all(v) (v).begin(),(v).end()
#define len(v) (int)(v).size()
#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
#define cmx(x,y) x=max(x,y)
#define cmn(x,y) x=min(x,y)
#define fi first
#define se second
#define pb push_back
#define show(x) cout<<#x<<" = "<<(x)<<endl
#define sar(a,n) cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl

using namespace std;

template<typename S,typename T>auto&operator<<(ostream&o,pair<S,T>p){return o<<"{"<<p.fi<<","<<p.se<<"}";}
template<typename T>auto&operator<<(ostream&o,set<T>s){for(auto&e:s)o<<e<<" ";return o;}
template<typename S,typename T,typename U>
auto&operator<<(ostream&o,priority_queue<S,T,U>q){while(!q.empty())o<<q.top()<<" ",q.pop();return o;}
template<typename K,typename T>auto&operator<<(ostream&o,map<K,T>m){for(auto&e:m)o<<e<<" ";return o;}
template<typename T>auto&operator<<(ostream&o,vector<T>v){for(auto&e:v)o<<e<<" ";return o;}
void ashow(){cout<<endl;}template<typename T,typename...A>void ashow(T t,A...a){cout<<t<<" ";ashow(a...);}

typedef pair<int,int> P;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef vector<P> vp;
typedef vector<double> vd;
typedef vector<string> vs;

const int MAX_N = 100005;

template <uint mod>
class ModInt {
private:
    uint v;
    static uint norm(const uint& x){ return x < mod ? x : x - mod; }
	static ModInt make(const uint& x){ ModInt m; return m.v = x, m; }
    static ModInt inv(const ModInt& x){ return make(inverse(x.v, mod)); }
    static uint inverse(int a, int m){
        int u[] = {a, 1, 0}, v[] = {m, 0, 1}, t;
        while(*v){
            t = *u / *v;
            swap(u[0] -= t * v[0], v[0]), swap(u[1] -= t * v[1], v[1]), swap(u[2] -= t * v[2], v[2]);
        }
        return (u[1] % m + m) % m;
    }

public:
    ModInt() : v{0}{}
    ModInt(const ll val) : v{norm(val % mod + mod)} {}
    ModInt(const ModInt<mod>& n) : v{n()} {}
	explicit operator bool() const noexcept { return v != 0; }
    bool operator!() const noexcept { return !static_cast<bool>(*this); }
    ModInt& operator=(const ModInt& n){ return v = n(), (*this); }
    ModInt& operator=(const ll val){ return v = norm(val % mod + mod), (*this); }
    ModInt operator+() const { return *this; }
    ModInt operator-() const { return v == 0 ? 0 : mod - v; }
    ModInt operator+(const ModInt& val) const { return make(norm(v + val())); }
    ModInt operator-(const ModInt& val) const { return make(norm(v + mod - val())); }
    ModInt operator*(const ModInt& val) const { return make((ll)v * val() % mod); }
    ModInt operator/(const ModInt& val) const { return *this * inv(val); }
    ModInt& operator+=(const ModInt& val){ return *this = *this + val; }
    ModInt& operator-=(const ModInt& val){ return *this = *this - val; }
    ModInt& operator*=(const ModInt& val){ return *this = *this * val; }
    ModInt& operator/=(const ModInt& val){ return *this = *this / val; }
    ModInt operator+(const ll val) const { return ModInt{v + val}; }
    ModInt operator-(const ll val) const { return ModInt{v - val}; }
    ModInt operator*(const ll val) const { return ModInt{(ll)v * (val % mod)}; }
    ModInt operator/(const ll val) const { return ModInt{(ll)v * inv(val)}; }
    ModInt& operator+=(const ll val){ return *this = *this + val; }
    ModInt& operator-=(const ll val){ return *this = *this - val; }
    ModInt& operator*=(const ll val){ return *this = *this * val; }
    ModInt& operator/=(const ll val){ return *this = *this / val; }
    bool operator==(const ModInt& val) const { return v == val.v; }
    bool operator!=(const ModInt& val) const { return !(*this == val); }
    bool operator==(const ll val) const { return v == norm(val % mod + mod); }
    bool operator!=(const ll val) const { return !(*this == val); }
    uint operator()() const { return v; }
    friend ModInt operator+(const ll val, const ModInt& n) { return n + val; }
    friend ModInt operator-(const ll val, const ModInt& n) { return ModInt{val - n()}; }
    friend ModInt operator*(const ll val, const ModInt& n) { return n * val; }
    friend ModInt operator/(const ll val, const ModInt& n) { return ModInt{val} / n; }
    friend bool operator==(const ll val, const ModInt& n) { return n == val; }
    friend bool operator!=(const ll val, const ModInt& n) { return !(val == n); }
    friend istream& operator>>(istream& is, ModInt& n){
        uint v;
        return is >> v, n = v, is;
    }
    friend ostream& operator<<(ostream& os, const ModInt& n){ return (os << n()); }
    friend ModInt power(ModInt x, ll n){
        ModInt ans = 1;
        while(n){
            if(n & 1) ans *= x;
            x *= x, n >>= 1;
        }
        return ans;
    }
};

template<typename T> class mat : public vector<vector<T> > {
private:
    int r, c;    //行,列
public:
    inline int row() const { return r; }
    inline int column() const { return c; }
    mat(const int n) : mat(n, n, 0){}
    mat(const int n, const int m, T val = 0)
        : vector<vector<T> >(n, vector<T>(m, val)), r{n}, c{m}{}
    mat operator+(const mat& another) const {
        mat<T> X(r, c);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < c; j++){
                X[i][j] = (*this)[i][j] + another[i][j];
            }
        }
        return X;
    }
    mat operator-(const mat& another) const {
        mat<T> X(r,c);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < c; j++){
                X[i][j] = (*this)[i][j] - another[i][j];
            }
        }
        return X;
    }
    mat operator*(const mat& another) const {
        mat<T> X(r, another.c);
        for(int i = 0; i < r; i++){
            for(int k = 0; k < c; k++){
                if(!(*this)[i][k]) continue;
                for(int j = 0; j < (another.c); j++){
                    X[i][j] += (*this)[i][k] * another[k][j];
                }
            }
        }
        return X;
    }
    vector<int> rank(){
        mat<T> X(r, c);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < c; j++){
                X[i][j] = (*this)[i][j];
            }
        }
        vector<int> index;
        int res = 0;
        for(int i = 0; i < c; i++){
            if(res == r) break;
            if(!X[res][i]){
                int pivot = res + 1;
                for(; pivot < r; pivot++){
                    if(X[pivot][i]){
                        swap(X[res], X[pivot]);
                        break;
                    }
                }
                if(pivot == r) continue;
            }
            const T p = (T)1 / X[res][i];
            for(int j = i + 1; j < c; j++){ X[res][j] *= p; }
            for(int j = res + 1; j < r; j++){
                if(!X[j][i]) continue;
                for(int k = i + 1; k < c; k++){
                    X[j][k] -= X[res][k] * X[j][i];
                }
            }
            index.push_back(i), ++res;
        }
        return index;
    }
    bool det_zero() const {
        mat<T> X(r);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < c; j++){
                X[i][j] = (*this)[i][j];
            }
        }
        for(int i = 0; i < c; i++){
            if(!X[i][i]){
                int pivot = i + 1;
                for(; pivot < r; pivot++){
                    if(X[pivot][i]){
                        swap(X[i], X[pivot]);
                        break;
                    }
                }
                if(pivot == r) return true;
            }
            const T p = (T)1 / X[i][i];
            for(int j = i + 1; j < c; j++){ X[i][j] *= p; }
            for(int j = i + 1; j < r; j++){
                if(!X[j][i]) continue;
                for(int k = i + 1; k < c; k++){
                    X[j][k] -= X[i][k] * X[j][i];
                }
            }
        }
        return false;
    }
    mat inverse() const {
        mat X(r, 2*r);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < r; j++){
                X[i][j] = (*this)[i][j];
            }
        }
        for(int i = 0; i < r; i++){
            X[i][r+i] = 1;
        }
        for(int i = 0; i < r; i++){
            if(!X[i][i]){
                int pivot = i + 1;
                for(; pivot < r; pivot++){
                    if(X[pivot][i]){
                        swap(X[i],X[pivot]);
                        break;
                    }
                }
                assert(pivot < r);
            }
            const T p = (T)1 / X[i][i];
            for(int j = i + 1; j < 2*r; j++){ X[i][j] *= p; }
            for(int j = 0; j < r; j++){
                if(i == j || !X[j][i]) continue;
                for(int k = i + 1; k < 2*r; k++){
                    X[j][k] -= X[i][k] * X[j][i];
                }
            }
        }
        mat res(r, r);
        for(int i = 0; i < r; i++){
            for(int j = 0; j < r; j++){
                res[i][j] = X[i][r+j];
            }
        }
        return res;
    }
};

class Matching {
private:
    const int V;
    vector<pair<int, int> > es;
    vector<int> index, cnt;
    random_device rnd;
	mt19937 mt;
    uniform_int_distribution<> randval;
    static constexpr int LOOP = 1;
    static constexpr uint mod = 1000000007;
    mat<ModInt<mod> > inverse_22(const int id, const mat<ModInt<mod> >& invT){
        ModInt<mod> invdev = (ModInt<mod>)1 / (invT[0][0]*invT[id][id] - invT[0][id]*invT[id][0]);
        mat<ModInt<mod> > invN_3n_3n(2, 2);
        invN_3n_3n[0][0] = invT[id][id] * invdev, invN_3n_3n[0][1] = -invT[0][id] * invdev;
        invN_3n_3n[1][0] = -invT[id][0] * invdev, invN_3n_3n[1][1] = invT[0][0] * invdev;
        return invN_3n_3n;
    }
    void schur_complement(const int id, mat<ModInt<mod> >& invT){
        int sz = invT.row(), x = 0;
        mat<ModInt<mod> >N_12_12(sz-2), N_12_3n(sz-2, 2), N_3n_12(2, sz-2);
        for(int i = 1; i < sz; i++){
            if(i == id) continue;
            int y = 0;
            for(int j = 1; j < sz; j++){
                if(j == id) continue;
                N_12_12[x][y] = invT[i][j];
                N_3n_12[0][y] = invT[0][j], N_3n_12[1][y++] = invT[id][j];
            }
            N_12_3n[x][0] = invT[i][0], N_12_3n[x++][1] = invT[i][id];
        }
        invT = N_12_12 - N_12_3n * inverse_22(id, invT) * N_3n_12;
    }
    void find_matching(const mat<ModInt<mod> >& T){
        int sz = T.row();
        mat<ModInt<mod> > invT = T.inverse();
        vector<int> vset(sz); iota(vset.begin(), vset.end(), 0);
        for(int i = sz; i > 0; i -= 2){
            for(int j = 1; j < i; j++){
                if(invT[0][j] && T[vset[0]][vset[j]]){
                    ans.emplace_back(index[vset[0]], index[vset[j]]);
                    vset.erase(vset.begin()), vset.erase(vset.begin() + j - 1);
                    schur_complement(j, invT);
                    break;
                }
            }
        }
    }

public:
    vector<pair<int, int> > ans;

    Matching(const int node_size)
        : V(node_size), cnt(V + 1, 0), mt(rnd()), randval(1, mod - 1){}
    void add_edge(const int u, const int v){ es.emplace_back(u, v); }
    bool perfect_matchching(){
        for(int i = 0; i < LOOP; i++){
            mat<ModInt<mod> > A(V);
            for(auto e : es){
                int r = randval(mt);
                A[e.first][e.second] = r, A[e.second][e.first] = -r;
            }
            if(!A.det_zero()) return true;
        }
        return false;
    }
    int maximum_matchching(){
        for(int i = 0; i < LOOP; i++){
            mat<ModInt<mod> > A(V);
            for(auto e : es){
                int r = randval(mt);
                A[e.first][e.second] = r, A[e.second][e.first] = -r;
            }
            vector<int> res = A.rank();
            ++cnt[res.size()];
            if((size_t)(max_element(cnt.begin(), cnt.end()) - cnt.begin()) == res.size()){
                index = move(res);
            }
        }
        return (int)(max_element(cnt.begin(), cnt.end()) - cnt.begin()) / 2;
    }
    int find_maximum_matching(){
        const int sz = maximum_matchching();
        vector<pair<int, int> > ans_tmp;
        vector<int> unzip(V, -1);
        for(int i = 0; i < 2 * sz; ++i) unzip[index[i]] = i;
        for(int i = 0; i < LOOP; i++){
            mat<ModInt<mod> > A(2 * sz);
            for(auto e : es){
                const int u = unzip[e.first], v = unzip[e.second];
                if(u < 0 || v < 0) continue;
                int r = randval(mt);
                A[u][v] = r, A[v][u] = -r;
            }
            if(!A.det_zero()){
                find_matching(A);
                break;
            }
        }
        return sz;
    }
};

int main()
{
    int n,m;
    cin >> n >> m;

    vector<set<int>> vs(n);
    vector<set<int>> containVs(m);
    for(int i = 0; m > i; i++) {
        int k;
        cin >> k;
        for(int j = 0; k > j; j++) {
            int v;
            cin >> v;
            v--;

            vs[v].insert(i);
            containVs[i].insert(v);
        }
    }

    int untouchcount = 0;
    queue<int> que;
    for(int i = 0; n > i; i++) {
        if(vs[i].size() == 1) {
            que.push(i);
        }
        if(vs[i].empty()) {
            untouchcount++;
        }
    }

    int erasedControls = 0;
    while(!que.empty()) {
        int c = que.front();
        que.pop();
        if(vs[c].size() == 0) continue;

        int ct = *(vs[c].begin());
        erasedControls++;
        for(int v : containVs[ct]) {
            vs[v].erase(ct);
            if(vs[v].size() == 1) que.push(v);
        }
    }

    Matching mt(m);
    for(int i = 0; n > i; i++) {
        if(vs[i].size() == 2) {
            mt.add_edge(*(vs[i].begin()), *(vs[i].rbegin()));
        }
    }

    mt.find_maximum_matching();
    cout << mt.ans.size() + untouchcount + erasedControls<< endl;

    return 0;
}
accuracy: 0.0425531914893617
time_ms: 70
memory_kb: 29044
final_rank: 20

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;



#define EPS 0.000000000001

#define SIZE 305

typedef vector<ll> V;
typedef vector<V> MATRIX;

int table[100005];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];
map<ll,bool> MAP;


ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}

ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}


int calc(MATRIX A){

	int N = A.size();

	MATRIX C(N,V(N));

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			C[row][col] = A[row][col];
		}
	}

	int ret = 0;

	for(int base = 0; base < N; base++){

		int row = -1;
		for(int i = base; i < N; i++){
			if(C[i][base] != 0){

				row = i;
				break;
			}
		}

		if(row == -1){
			continue;
		}

		ret++;

		if(row != base){

			swap(C[row],C[base]);
		}

		for(int i= base+1; i < N; i++){

			ll tmp = C[i][base]*mod_inverse(C[base][base],MOD)%MOD;
			for(int k = base; k < N; k++){
				C[i][k] -= tmp*C[base][k]%MOD;
				if(C[i][k] < 0){
					C[i][k] = abs(C[i][k])%MOD;
					C[i][k] *= -1;
					C[i][k] += MOD;
				}
			}
		}
	}
	//printf("ret:%d\n",ret);
	return (ret+1)/2;
}



mt19937_64 mt;

ll get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	MATRIX A(M,V(M));
	for(int row = 0; row < M; row++){
		for(int col = 0; col < M; col++){
			A[row][col] = 0;
			check[row][col] = false;
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
	}

	int ans = 0;
	for(int i = 0; i < N; i++){

		if(table[i] == 0){
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			used[vec[i][0]] = true;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	MAP[0] = true;

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			while(true){
				ll rand_num = get_rand()%MOD;

				auto at = MAP.find(rand_num);
				if(at != MAP.end())continue;
				MAP[rand_num] = true;

				//printf("rand_num:%lld\n",rand_num);

				A[i][k] = rand_num;
				A[k][i] = -rand_num;

				break;
			}
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp);

	return 0;
}
accuracy: 1
time_ms: 70
memory_kb: 10996
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;



#define EPS 0.000000000001

#define SIZE 305

typedef vector<ll> V;
typedef vector<V> MATRIX;

int table[100005];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];


ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}

ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}


int calc(MATRIX A){

	int N = A.size();

	MATRIX C(N,V(N));

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			C[row][col] = A[row][col];
		}
	}

	int ret = 0;

	for(int base = 0; base < N; base++){

		int row = -1;
		for(int i = base; i < N; i++){
			if(C[i][base] != 0){

				row = i;
				break;
			}
		}

		if(row == -1){
			printf("N:%d base:%d\n",N,base);
			break;
		}

		ret++;

		if(row != base){

			swap(C[row],C[base]);
		}

		for(int i= base+1; i < N; i++){

			//C[i][base]が0でもSKIPするとWAになる場合あり(AOJ 2347 Sunny Graph)

			ll tmp = C[i][base]*mod_inverse(C[base][base],MOD)%MOD;
			for(int k = base; k < N; k++){
				C[i][k] -= tmp*C[base][k]%MOD;
				if(C[i][k] < 0){
					C[i][k] = abs(C[i][k])%MOD;
					C[i][k] *= -1;
					C[i][k] += MOD;
				}
			}
		}
	}
	//printf("ret:%d\n",ret);
	return (ret+1)/2;
}



mt19937_64 mt;

ll get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	MATRIX A(M,V(M));
	for(int row = 0; row < M; row++){
		for(int col = 0; col < M; col++){
			A[row][col] = 0;
			check[row][col] = false;
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
	}

	int ans = 0;
	for(int i = 0; i < N; i++){

		if(table[i] == 0){
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			used[vec[i][0]] = true;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			ll rand_num = get_rand()%MOD;

			A[i][k] = rand_num;
			A[k][i] = -rand_num;

			if(rand()%2){

				swap(A[i][k],A[k][i]);
			}
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp);

	return 0;
}
accuracy: 0.0425531914893617
time_ms: 40
memory_kb: 10960
final_rank: 19

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;



#define EPS 0.0000000001

#define SIZE 305

typedef vector<long double> V;
typedef vector<V> MATRIX;

int table[100005];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

int calc(MATRIX A){

	int H = A.size();
	int W = A[0].size();

	MATRIX C(H,V(W+1));

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			C[row][col] = A[row][col];
		}
		C[row][W] = 0;
	}

	int base_row;
	long double tmp;

	int ret = 0;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < W; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue;

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col <= W; col++){
			C[i][col] /= tmp;
		}

		for(int row = 0; row < H; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue;

			tmp = C[row][i];

			for(int col = i; col <= W; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}

		ret++;
	}

	return (ret/2-ret%2);
}

mt19937_64 mt;

double get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	MATRIX A(M,V(M));
	for(int row = 0; row < M; row++){
		for(int col = 0; col < M; col++){
			A[row][col] = 0;
			check[row][col] = false;
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
	}

	int ans = 0;
	for(int i = 0; i < N; i++){

		if(table[i] == 0){
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			used[vec[i][0]] = true;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			ll rand_num = get_rand();

			A[i][k] = rand_num;
			A[k][i] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp);

	return 0;
}
accuracy: 0.14893617021276595
time_ms: 20
memory_kb: 13060
final_rank: 13

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;



#define EPS 0.0000001

#define SIZE 305

typedef vector<double> V;
typedef vector<V> MATRIX;

int table[100005];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

int calc(MATRIX A){

	int H = A.size();
	int W = A[0].size();

	MATRIX C(H,V(W+1));

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			C[row][col] = A[row][col];
		}
		C[row][W] = 0;
	}

	int base_row;
	double tmp;

	int ret = 0;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < W; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue;

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col <= W; col++){
			C[i][col] /= tmp;
		}

		for(int row = 0; row < H; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue;

			tmp = C[row][i];

			for(int col = i; col <= W; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}

		ret++;
	}

	return ret;
}

mt19937_64 mt;

double get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	MATRIX A(M,V(M));
	for(int row = 0; row < M; row++){
		for(int col = 0; col < M; col++){
			A[row][col] = 0;
			check[row][col] = false;
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
	}

	int ans = 0;
	for(int i = 0; i < N; i++){

		if(table[i] == 0){
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			used[vec[i][0]] = true;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			ll rand_num = get_rand();

			A[i][k] = rand_num;
			A[k][i] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp/2);

	return 0;
}
accuracy: 0.8936170212765957
time_ms: 20
memory_kb: 10988
final_rank: 9

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;



#define SIZE 305

typedef vector<ll> V;
typedef vector<V> MATRIX;

int table[100005],INDEX[SIZE];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

#define EPS 0.00000000001

ll gcd(ll x,ll y){

	x = abs(x);
	y = abs(y);

	if(x < y){
		swap(x,y);
	}
	if(y == 0){
		return x;
	}else{
		return gcd(y,x%y);
	}
}

ll lcm(ll x,ll y){

	return (x*y)/gcd(x,y);
}

ll extgcd(ll a,ll b,ll &x,ll &y){
	ll d = a;
	if(b != 0){
		d = extgcd(b,a%b,y,x);
		y -= (a/b)*x;
	}else{
		x = 1;
		y = 0;
	}
	return d;
}

ll mod_inverse(ll a,ll m){
    ll x,y;
    extgcd(a,m,x,y);
    return (m+x%m)%m;
}


int calc(MATRIX A){

	int N = A.size();

	MATRIX C(N,V(N));

	for(int row = 0; row < N; row++){
		for(int col = 0; col < N; col++){
			C[row][col] = (A[row][col]+MOD)%MOD;
		}
	}

	ll mult = 1;
	int ret = 0;

	for(int base = 0; base < N; base++){

		int row = -1;
		for(int i = base; i < N; i++){
			if(C[i][base] != 0){

				row = i;
				break;
			}
		}

		if(row == -1)break;

		ret++;

		if(row != base){

			swap(C[row],C[base]);
			mult *= (-1+MOD)%MOD;
			mult %= MOD;
		}

		for(int i= base+1; i < N; i++){

			ll tmp = C[i][base]*mod_inverse(C[base][base],MOD)%MOD;
			for(int k = base; k < N; k++){
				C[i][k] -= tmp*C[base][k]%MOD;
				if(C[i][k] < 0){
					C[i][k] = abs(C[i][k])%MOD;
					C[i][k] *= -1;
					C[i][k] += MOD;
				}
			}
		}
	}

	return ret/2;
}



mt19937_64 mt;

ll get_rand(){

	return mt()%MOD;
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
		for(int k = 0; k < M; k++){

			check[i][k] = false;
		}
	}

	int ans = 0;
	int num_used = 0;

	for(int i = 0; i < N; i++){

		if(table[i] == 0){

			//printf("数が0\n");
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			//printf("1回だけ\n");
			used[vec[i][0]] = true;
			num_used++;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	int index = 0;

	for(int i = 0; i < M; i++){
		if(used[i])continue;

		INDEX[i] = index++;
	}

	//printf("index:%d\n",index);

	MATRIX A(index,V(index));
	for(int row = 0; row < index; row++){
		for(int col = 0; col < index; col++){
			A[row][col] = 0;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			ll rand_num = get_rand();

			A[INDEX[i]][INDEX[k]] = rand_num;
			A[INDEX[k]][INDEX[i]] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp);

	return 0;
}
accuracy: 0.0851063829787234
time_ms: 40
memory_kb: 10996
final_rank: 16

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;



#define SIZE 305

typedef vector<double> V;
typedef vector<V> MATRIX;

int table[100005],INDEX[SIZE];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

#define EPS 0.00000000001

int calc(MATRIX A){

	int H = A.size();
	int W = A[0].size();

	MATRIX C(H,V(W));

	//printf("H:%d\n",H);

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			C[row][col] = A[row][col];
		}
	}

	int base_row;
	double tmp;

	int ret = 0;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < H; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue;

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col < W; col++){
			C[i][col] /= tmp;
		}

		for(int row = 0; row < H; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue;

			tmp = C[row][i];

			for(int col = i; col < W; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}
		ret++;
	}

	//printf("ret:%d\n",ret);
	return ret/2;
}

mt19937_64 mt;

double get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
		for(int k = 0; k < M; k++){

			check[i][k] = false;
		}
	}

	int ans = 0;
	int num_used = 0;

	for(int i = 0; i < N; i++){

		if(table[i] == 0){

			//printf("数が0\n");
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			//printf("1回だけ\n");
			used[vec[i][0]] = true;
			num_used++;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	int index = 0;

	for(int i = 0; i < M; i++){
		if(used[i])continue;

		INDEX[i] = index++;
	}

	//printf("index:%d\n",index);

	MATRIX A(index,V(index));
	for(int row = 0; row < index; row++){
		for(int col = 0; col < index; col++){
			A[row][col] = 0;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			double rand_num = get_rand();
			if(rand()%2)rand_num *= -1;

			A[INDEX[i]][INDEX[k]] = rand_num;
			A[INDEX[k]][INDEX[i]] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp);

	return 0;
}
accuracy: 0.0851063829787234
time_ms: 20
memory_kb: 10956
final_rank: 14

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
//#define EPS 0.000000001
using namespace std;



#define SIZE 305

typedef vector<double> V;
typedef vector<V> MATRIX;

int table[100005],INDEX[SIZE];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

#define EPS 0.00000000001

int calc(MATRIX A){

	int H = A.size();
	int W = A[0].size();

	MATRIX C(H,V(W));

	//printf("H:%d\n",H);

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			C[row][col] = A[row][col];
		}
	}

	int base_row;
	double tmp;

	int ret = 0;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < H; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue;

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col < W; col++){
			C[i][col] /= tmp;
		}

		for(int row = 0; row < H; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue;

			tmp = C[row][i];

			for(int col = i; col < W; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}
		ret++;
	}

	//printf("ret:%d\n",ret);
	return ret/2;
}

mt19937_64 mt;

double get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
		for(int k = 0; k < M; k++){

			check[i][k] = false;
		}
	}

	int ans = 0;
	int num_used = 0;

	for(int i = 0; i < N; i++){

		if(table[i] == 0){

			//printf("数が0\n");
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			//printf("1回だけ\n");
			used[vec[i][0]] = true;
			num_used++;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	int index = 0;

	for(int i = 0; i < M; i++){
		if(used[i])continue;

		INDEX[i] = index++;
	}

	//printf("index:%d\n",index);

	MATRIX A(index,V(index));
	for(int row = 0; row < index; row++){
		for(int col = 0; col < index; col++){
			A[row][col] = 0;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			double rand_num = get_rand();
			if(((ll)get_rand())%2)rand_num *= -1;

			A[INDEX[i]][INDEX[k]] = rand_num;
			A[INDEX[k]][INDEX[i]] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp);

	return 0;
}
accuracy: 0.19148936170212766
time_ms: 20
memory_kb: 11064
final_rank: 10

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 305

typedef vector<double> V;
typedef vector<V> MATRIX;

int table[100005],INDEX[SIZE];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

int calc(MATRIX A){

	int H = A.size();
	int W = A[0].size();

	MATRIX C(H,V(W));

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			C[row][col] = A[row][col];
		}
	}

	int base_row;
	double tmp;

	int ret = 0;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < H; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue;

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col < W; col++){
			C[i][col] /= tmp;
		}

		for(int row = 0; row < H; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue;

			tmp = C[row][i];

			for(int col = i; col < W; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}
		ret++;
	}

	return (ret+1)/2;
}

mt19937_64 mt;

double get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
		for(int k = 0; k < M; k++){

			check[i][k] = false;
		}
	}

	int ans = 0;
	int num_used = 0;

	for(int i = 0; i < N; i++){

		if(table[i] == 0){

			//printf("数が0\n");
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			//printf("1回だけ\n");
			used[vec[i][0]] = true;
			num_used++;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	int index = 0;

	for(int i = 0; i < M; i++){
		if(used[i])continue;

		INDEX[i] = index++;
	}

	//printf("index:%d\n",index);

	MATRIX A(index,V(index));
	for(int row = 0; row < index; row++){
		for(int col = 0; col < index; col++){
			A[row][col] = 0;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			double rand_num = get_rand();

			A[INDEX[i]][INDEX[k]] = rand_num;
			A[INDEX[k]][INDEX[i]] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp);

	return 0;
}
accuracy: 0.14893617021276595
time_ms: 10
memory_kb: 11032
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 305

typedef vector<double> V;
typedef vector<V> MATRIX;

int table[100005],INDEX[SIZE];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

int calc(MATRIX A){

	int H = A.size();
	int W = A[0].size();

	MATRIX C(H,V(W));

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			C[row][col] = A[row][col];
		}
	}

	int base_row;
	double tmp;

	int ret = 0;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < H; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue;

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col < W; col++){
			C[i][col] /= tmp;
		}

		for(int row = 0; row < H; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue;

			tmp = C[row][i];

			for(int col = i; col < W; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}
		ret++;
	}

	return ret/2;
}

mt19937_64 mt;

double get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
		for(int k = 0; k < M; k++){

			check[i][k] = false;
		}
	}

	int ans = 0;
	int num_used = 0;

	for(int i = 0; i < N; i++){

		if(table[i] == 0){

			//printf("数が0\n");
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			//printf("1回だけ\n");
			used[vec[i][0]] = true;
			num_used++;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	int index = 0;

	for(int i = 0; i < M; i++){
		if(used[i])continue;

		INDEX[i] = index++;
	}

	//printf("index:%d\n",index);

	MATRIX A(index,V(index));
	for(int row = 0; row < index; row++){
		for(int col = 0; col < index; col++){
			A[row][col] = 0;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			double rand_num = get_rand();

			A[INDEX[i]][INDEX[k]] = rand_num;
			A[INDEX[k]][INDEX[i]] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp);

	return 0;
}
accuracy: 0.0851063829787234
time_ms: 20
memory_kb: 11056
final_rank: 15

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 305

typedef vector<double> V;
typedef vector<V> MATRIX;

int table[100005],INDEX[SIZE];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

int calc(MATRIX A){

	int H = A.size();
	int W = A[0].size();

	MATRIX C(H,V(W));

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			C[row][col] = A[row][col];
		}
	}

	int base_row;
	double tmp;

	int ret = 0;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < H; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue;

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col < W; col++){
			C[i][col] /= tmp;
		}

		for(int row = 0; row < H; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue;

			tmp = C[row][i];

			for(int col = i; col < W; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}
		ret++;
	}

	return ret;
}

mt19937_64 mt(rand());

double get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
		for(int k = 0; k < M; k++){

			check[i][k] = false;
		}
	}

	int ans = 0;
	int num_used = 0;

	for(int i = 0; i < N; i++){

		if(table[i] == 0){

			//printf("数が0\n");
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			//printf("1回だけ\n");
			used[vec[i][0]] = true;
			num_used++;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	int index = 0;

	for(int i = 0; i < M; i++){
		if(used[i])continue;

		INDEX[i] = index++;
	}

	//printf("index:%d\n",index);

	MATRIX A(index,V(index));
	for(int row = 0; row < index; row++){
		for(int col = 0; col < index; col++){
			A[row][col] = 0;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			double rand_num = get_rand();

			A[INDEX[i]][INDEX[k]] = rand_num;
			A[INDEX[k]][INDEX[i]] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+(tmp/2-tmp%2));

	return 0;
}
accuracy: 0.14893617021276595
time_ms: 20
memory_kb: 10960
final_rank: 12

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 9223372036854775807
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define SIZE 305

typedef vector<double> V;
typedef vector<V> MATRIX;

int table[100005];
bool used[SIZE],check[SIZE][SIZE];
vector<int> vec[100005],G[SIZE];

int calc(MATRIX A){

	int H = A.size();
	int W = A[0].size();

	MATRIX C(H,V(W+1));

	for(int row = 0; row < H; row++){
		for(int col = 0; col < W; col++){
			C[row][col] = A[row][col];
		}
		C[row][W] = 0;
	}

	int base_row;
	double tmp;

	int ret = 0;

	for(int i = 0; i < H; i++){
		base_row = i;
		for(int row = i+1; row < W; row++){
			if(fabs(C[row][i]) > fabs(C[base_row][i])){
				base_row = row;
			}
		}

		if(fabs(C[base_row][i]) < EPS)continue;

		if(base_row != i)swap(C[base_row],C[i]);

		tmp = C[i][i]; //係数
		for(int col = 0; col <= W; col++){
			C[i][col] /= tmp;
		}

		for(int row = 0; row < H; row++){
			if(row == i || fabs(C[row][i]) < EPS)continue;

			tmp = C[row][i];

			for(int col = i; col <= W; col++){
				C[row][col] -= C[i][col]*tmp;
			}
		}

		ret++;
	}

	return ret;
}

mt19937_64 mt;

double get_rand(){

	return mt();
}


int main(){

	int N,M;
	scanf("%d %d",&N,&M);

	for(int i = 0; i < N; i++){

		table[i] = 0;
	}

	int num,tmp;

	for(int i = 0; i < M; i++){

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			scanf("%d",&tmp);
			tmp--;

			table[tmp]++;
			vec[tmp].push_back(i);
		}
	}

	MATRIX A(M,V(M));
	for(int row = 0; row < M; row++){
		for(int col = 0; col < M; col++){
			A[row][col] = 0;
			check[row][col] = false;
		}
	}

	for(int i = 0; i < M; i++){

		used[i] = false;
	}

	int ans = 0;
	for(int i = 0; i < N; i++){

		if(table[i] == 0){
			ans++;
		}else if(table[i] == 1){

			if(used[vec[i][0]])continue;
			used[vec[i][0]] = true;
			ans++;

		}else{ //table[i] == 2

			check[vec[i][0]][vec[i][1]] = true;
			check[vec[i][1]][vec[i][0]] = true;
		}
	}

	for(int i = 0; i < M-1; i++){
		if(used[i])continue;
		for(int k = i+1; k < M; k++){
			if(used[k])continue;
			if(!check[i][k])continue;

			ll rand_num = get_rand();

			A[i][k] = rand_num;
			A[k][i] = -rand_num;
		}
	}


	tmp = calc(A);
	//printf("ans:%d tmp:%d\n",ans,tmp);

	printf("%d\n",ans+tmp/2);

	return 0;
}
accuracy: 0.8936170212765957
time_ms: 20
memory_kb: 10956
final_rank: 8

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

using Int = long long;
using ll = long long;

template<typename T1,typename T2> inline void chmin(T1 &a,T2 b){if(a>b)a=b;};
template<typename T1,typename T2> inline void chmax(T1 &a,T2 b){if(a<b)a=b;};

template<typename T> void drop(T x){cout<<x<<endl;exit(0);};


template<typename T,T MOD = 1000000007>
struct Mint{
  static constexpr T mod = MOD;
  T v;
  Mint():v(0){}
  Mint(signed v):v(v){}
  Mint(long long t){v=t%MOD;if(v<0) v+=MOD;}

  Mint pow(long long k){
    Mint res(1),tmp(v);
    while(k){
      if(k&1) res*=tmp;
      tmp*=tmp;
      k>>=1;
    }
    return res;
  }

  static Mint add_identity(){return Mint(0);}
  static Mint mul_identity(){return Mint(1);}

  Mint inv(){return pow(MOD-2);}

  Mint& operator+=(Mint a){v+=a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator-=(Mint a){v+=MOD-a.v;if(v>=MOD)v-=MOD;return *this;}
  Mint& operator*=(Mint a){v=1LL*v*a.v%MOD;return *this;}
  Mint& operator/=(Mint a){return (*this)*=a.inv();}

  Mint operator+(Mint a) const{return Mint(v)+=a;};
  Mint operator-(Mint a) const{return Mint(v)-=a;};
  Mint operator*(Mint a) const{return Mint(v)*=a;};
  Mint operator/(Mint a) const{return Mint(v)/=a;};

  Mint operator-() const{return v?Mint(MOD-v):Mint(v);}

  bool operator==(const Mint a)const{return v==a.v;}
  bool operator!=(const Mint a)const{return v!=a.v;}
  bool operator <(const Mint a)const{return v <a.v;}

  // find x s.t. a^x = b
  static T log(T a,T b){
    const T sq=40000;
    unordered_map<T, T> dp;
    dp.reserve(sq);
    Mint res(1);
    for(int r=0;r<sq;r++){
      if(!dp.count(res.v)) dp[res.v]=r;
      res*=a;
    }
    Mint p=Mint(a).inv().pow(sq);
    res=b;
    for(int q=0;q<=MOD/sq+1;q++){
      if(dp.count(res.v)){
        T idx=q*sq+dp[res.v];
        if(idx>0) return idx;
      }
      res*=p;
    }
    assert(0);
    return T(-1);
  }

  static Mint comb(long long n,int k){
    Mint num(1),dom(1);
    for(int i=0;i<k;i++){
      num*=Mint(n-i);
      dom*=Mint(i+1);
    }
    return num/dom;
  }
};
template<typename T,T MOD> constexpr T Mint<T, MOD>::mod;
template<typename T,T MOD>
ostream& operator<<(ostream &os,Mint<T, MOD> m){os<<m.v;return os;}

//INSERT ABOVE HERE
int maximal_matching(vector< vector<int> > G){
  int n=G.size();

  random_device rd;
  mt19937 mt(rd());
  using M = Mint<int>;
  uniform_int_distribution<int> ud(1,M::mod-1);

  vector< vector<M> > H(n,vector<M>(n,0));
  for(int v=0;v<n;v++){
    for(int u:G[v]){
      if(u>=v) continue;
      M val(ud(mt));
      H[u][v]= val;
      H[v][u]=-val;
    }
  }

  int res=0;
  for(int i=0,j=0;i<n;i++){
    while(j<n&&H[i][j]==M(0)){
      int p=i;
      for(int k=i+1;k<n;k++)
        if(H[k][j]!=M(0)) p=k;
      if(i!=p) swap(H[i],H[p]);
      else j++;
    }
    if(j==n) break;
    M tmp=H[i][j].inv();
    for(int s=j;s<n;s++) H[i][s]*=tmp;
    for(int k=i+1;k<n;k++)
      for(int s=n-1;s>=j;s--)
        H[k][s]-=H[k][j]*H[i][s];

    j++;res++;
  }
  return (res+1)/2;
}

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

  int n,m;
  cin>>n>>m;
  vector< vector<int> > L(m);
  for(int i=0;i<m;i++){
    int k;
    cin>>k;
    L[i].resize(k);
    for(int j=0;j<k;j++) cin>>L[i][j],L[i][j]--;
  }

  vector< vector<int> > G(n);
  for(int i=0;i<m;i++){
    for(int v:L[i]) G[v].emplace_back(i);
  }

  int taken=0;
  vector<int> dead(m,0);
  for(int i=0;i<n;i++){
    if(G[i].size()<=1u){
      int flg=0;
      for(int g:G[i]) if(dead[g]) flg=1;
      if(flg) continue;
      taken++;
      for(int g:G[i]) dead[g]=1;
    }
  }

  vector< vector<int> > H(m);
  for(int i=0;i<n;i++){
    if(G[i].size()<=1u) continue;
    int x=G[i][0];
    int y=G[i][1];
    if(dead[x]||dead[y]) continue;
    H[x].emplace_back(y);
    H[y].emplace_back(x);
  }

  int ans=taken+maximal_matching(H);
  cout<<ans<<endl;
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 11852
final_rank: 4