// Arup Guha
// 10/17/2021
// Solution to 2021 UCF Locals Final Round Problem: Discord Daisy Chain

import java.util.*;
import java.io.*;

public class discord {
	
    final public static int UNVISITED = -1;

    public static int numVertices;
    public static ArrayList[] eList;
    public static int[] dfsNum;
    public static int[] dfsLow;
    public static boolean[] visited;
    public static Stack<Integer> myStack;
    public static int vIndex;
    public static int sccNum;	
	public static int[] compNum;
	
	public static void main(String[] args) throws Exception {
	
		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());
		numVertices = Integer.parseInt(tok.nextToken());
		int numBots = Integer.parseInt(tok.nextToken());
		
		// Set up graoh.
        eList = new ArrayList[numVertices];
        for (int i=0; i<numVertices; i++)
            eList[i] = new ArrayList<Integer>();

		// Set up Tarjan's.
        dfsNum = new int[numVertices];
        Arrays.fill(dfsNum, UNVISITED);
        dfsLow = new int[numVertices];
		compNum = new int[numVertices];
        visited = new boolean[numVertices];
        myStack = new Stack<Integer>();
        vIndex = 0;

		// Go through bots.
		for (int i=0; i<numBots; i++) {
			
			// Get starting vertex.
			tok = new StringTokenizer(stdin.readLine());
			int u = Integer.parseInt(tok.nextToken())-1;
			int numF = Integer.parseInt(tok.nextToken());
			
			// Add each edge from starting vertex.
			for (int j=0; j<numF; j++) {
				int v = Integer.parseInt(tok.nextToken())-1;
				eList[u].add(v);
			}
		}
		
		// Run Tarjan's.
		wrapper();
		
		// Get size of each SCC.
		int[] sizes = new int[sccNum];
		for (int i=0; i<numVertices; i++) sizes[compNum[i]]++;
		
		// Make smaller DAG.
		HashSet[] smallG = new HashSet[sccNum];
		for (int i=0; i<sccNum; i++) smallG[i] = new HashSet<Integer>();
		
		boolean[] hasIn = new boolean[sccNum];
		
		// Here we add all of the new edges.
		for (int i=0; i<numVertices; i++) {
			for (Integer v: (ArrayList<Integer>)eList[i]) {
				if (compNum[v] != compNum[i]) {
					smallG[compNum[i]].add(compNum[v]);
					hasIn[compNum[v]] = true;
				}
			}
		}
		
		// All we care about are strongly connected components with no incoming edges.
		int noInVal = -1, noInCnt = 0;
		for (int i=0; i<sccNum; i++) {
			if (!hasIn[i]) {
				noInVal = i;
				noInCnt++;
			}
		}
		
		// This case is easy.
		if (noInCnt > 1)
			System.out.println(0);
		
		// Here we must see if we can reach everything from this component.
		else {
			
			// Run a regular DFS from our node noInVal.
			boolean[] visited = new boolean[sccNum];
			dfs(smallG, noInVal, visited);
			
			// See if it got to everything.
			boolean all = true;
			for (int i=0; i<sccNum; i++)
				if (!visited[i])
					all = false;
			
			// Ta da!
			if (all)
				System.out.println(sizes[noInVal]);
			else
				System.out.println(0);
		}
	}
	
	// Runs a regular DFS on g from vertex v.
	public static void dfs(HashSet[] g, int v, boolean[] visited) {
		visited[v] = true;
		for (Integer x: (HashSet<Integer>)g[v])
			if (!visited[x])
				dfs(g, x, visited);
	}

	public static void wrapper() {
        sccNum = 0;

        // Run Tarjan on each unvisited node.
        for (int i=0; i<numVertices; i++)
            if (dfsNum[i] == UNVISITED)
                tarjan(i);		
	}

    public static void tarjan(int node) {

        // Initial numbers for these nodes.
        dfsLow[node] = vIndex;
        dfsNum[node] = vIndex;
        vIndex++;
        myStack.push(node);

        // Mark this node.
        visited[node] = true;

        // Recursively visit each neighbor.
        for (int i=0; i<eList[node].size(); i++) {

            // Regular DFS here.
            int next = (Integer)eList[node].get(i);
            if (dfsNum[next] == UNVISITED)
                tarjan(next);

            // Needed to update dfsLow.
            if (visited[next])
                dfsLow[node] = Math.min(dfsLow[node], dfsLow[next]);
        }

        // This is a start of a SCC.
        if (dfsLow[node] == dfsNum[node]) {

            // Pop back items in SCC.
            while (true) {
                int prev = myStack.pop();
				compNum[prev] = sccNum;
                visited[prev] = false;
                if (node == prev) break;
            }
			
			sccNum++;
        }
    }
}