//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3")
//~ #pragma GCC target ("avx2")
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
template <typename T>
using ordered_set =
tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
*this << "[";
for (auto it = d.b; it != d.e; ++it)
*this << ", " + 2 * (it == d.b) << *it;
ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#define shandom_ruffle random_shuffle
using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;
const int nax=1000*1007;
int n, q;
vector<pii> kra[nax];
vi graf[nax];
int sko[nax];
int ma[nax];
int bylo[nax];
vi farg[nax];
int cov[nax][2];
int odw[nax][2];
int dfs1(int v)
{
bylo[v]=1;
for (int i : graf[v])
{
if (!ma[i] || (!bylo[ma[i]] && dfs1(ma[i])))
{
sko[v]=i;
ma[i]=v;
return 1;
}
}
return 0;
}
int szukaj(int v)
{
for (int i=1; i<=n; i++)
{
graf[i].clear();
farg[i].clear();
}
for (int i=1; i<=v; i++)
{
for (pii j : kra[i])
{
graf[j.first].push_back(j.second);
farg[j.second].push_back(j.first);
}
}
int czy=1;
int ret=0;
while(czy)
{
czy=0;
for (int i=1; i<=n; i++)
bylo[i]=0;
for (int i=1; i<=n; i++)
if (!sko[i] && !bylo[i] && dfs1(i))
czy=1, ret++;
}
return ret;
}
void dfs2(int v, int war, int parz)
{
if (odw[v][war])
return;
odw[v][war]=1;
cov[v][war]=parz;
if (!war)
{
if (!parz)
for (int i : graf[v])
dfs2(i, 1, parz^1);
else
dfs2(sko[v], 1, parz^1)
}
else
{
if (!parz)
for (int i : farg[v])
dfs2(i, 0, parz^1);
else
dfs2(ma[v], 0, parz^1);
}
}
void cover()
{
for (int i=1; i<=n; i++)
for (int h=0; h<2; h++)
odw[i][h]=cov[i][h]=0;
for (int i=1; i<=n; i++)
if (!sko[i])
dfs2(i, 0, 0);
for (int i=1; i<=n; i++)
if (!ma[i])
dfs2(i, 1, 0);
for (int i=1; i<=n; i++)
for (int j=0; j<2; j++)
if (!odw[i][j])
cov[i][j]=1;
}
int main()
{
scanf("%d%d", &n, &q);
for (int i=1; i<=q; i++)
{
int r;
scanf("%d", &r);
while(r--)
{
int a, b;
scanf("%d%d", &a, &b);
kra[i].push_back({a, b});
}
}
int sum=0;
for (int i=1; i<=q; i++)
{
sum+=szukaj(i);
printf("%d ", sum);
cover();
//~ debug();
//~ for (int j=1; j<=n; j++)
//~ debug() << j << " " << cov[j][0] << " " << cov[j][1];
//~ for (int j=(int)kra[i].size()-1; j>=0; j--)
//~ {
//~ if (cov[kra[i][j].first][0] && cov[kra[i][j].second][1])
//~ {
//~ swap(kra[i][j], kra[i].back());
//~ kra[i].pop_back();
//~ }
//~ }
for (int h=1; h<=i; h++)
{
for (int j=(int)kra[h].size()-1; j>=0; j--)
{
if (cov[kra[h][j].first][0] && cov[kra[h][j].second][1])
{
swap(kra[h][j], kra[h].back());
kra[h].pop_back();
}
}
}
for (int h=i+1; h<=q; h++)
{
for (int j=(int)kra[h].size()-1; j>=0; j--)
{
if (cov[kra[h][j].first][0] || cov[kra[h][j].second][1])
{
swap(kra[h][j], kra[h].back());
kra[h].pop_back();
}
}
}
}
printf("\n");
return 0;
}