#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long ll; typedef vector VI; typedef pair PII; #define REP(i,s,t) for(int i=(s);i<(t);i++) #define FILL(x,v) memset(x,v,sizeof(x)) #define MAXN 1005 VI g[MAXN], adj[MAXN]; int curSplit[MAXN], C; void removeEdge(VI &es, int x) { int sz = es.size(); REP(i,0,sz) { if (es[i] == x) { swap(es[i], es[sz - 1]); es.pop_back(); return; } } } int findCut(int exclude = -1) { int cut = 0; REP(gx,0,C) { int cx = curSplit[g[gx][0]]; for (auto &gy: adj[gx]) { if (gy < gx || gx == exclude || gy == exclude) continue; int cy = curSplit[g[gy][0]]; if (cx != cy) cut++; } } return cut; } int main() { int n, m; cin >> n >> m; REP(i,1,n+1) g[0].push_back(i); C = 1; while (m--) { int s, x; cin >> s; FILL(curSplit, 0); REP(j,0,s) { cin >> x; curSplit[x] = 1; } int split = -1; REP(i,0,C) { bool has[2] = {}; for (auto &x: g[i]) has[curSplit[x]] = true; if (has[0] && has[1]) { if (split != -1) return cout << 0 << endl, 0; split = i; } } if (split == -1) { int cut = findCut(); assert(cut != 0); if (cut != 1) return cout << 0 << endl, 0; continue; } else if (findCut(split) > 0) return cout << 0 << endl, 0; VI g0, g1; for (auto &gx: adj[split]) { int x = g[gx][0]; if (curSplit[x] == 0) g0.push_back(gx); else g1.push_back(gx); } VI curg = g[split], curAdj = adj[split]; g[split].clear(); for (auto &x: curg) { if (curSplit[x] == 0) g[split].push_back(x); else g[C].push_back(x); } for (auto &gx: curAdj) { removeEdge(adj[gx], split); } adj[split].clear(); for (auto &gx: g0) { adj[gx].push_back(split); adj[split].push_back(gx); } for (auto &gx: g1) { adj[gx].push_back(C); adj[C].push_back(gx); } adj[split].push_back(C); adj[C].push_back(split); C++; } cout << 1 << endl; return 0; }