import ru.ifmo.validate.*;
import java.util.*;

public class Validate implements Validator {
	static final int MAX_N = 50000;
	static final int MAX_M = 50000;
	static final int MAX_K = 1000;

	private final static int WHITE = 0;
	private final static int GREY = 1;
	private final static int BLACK = 2;

	private class Edge implements Comparable<Edge> {
		private final int v1;
		private final int v2;
		private boolean inCycle;

		public Edge(int v1, int v2) {
			if (v1 > v2) {
				int p = v1;
				v1 = v2;
				v2 = p;
			}
			this.v1 = v1;
			this.v2 = v2;
		}

		public int compareTo(Edge e) {
			return v1 == e.v1 ? v2 - e.v2 : v1 - e.v1;
		}

		public int other(int v) {
			return v == v1 ? v2 : v1;
		}
	}

	private Edge[] inEdge;
	private int[] state;
	private List<Edge>[] edges;
	boolean f;

	void dfs(int i, Edge e) {
		inEdge[i] = e;
		state[i] = GREY;
		for (Edge edge : edges[i]) {
			int j = edge.other(i);

			if (state[j] == WHITE) {
				dfs(j, edge);
			} else if (state[j] == GREY && j != inEdge[i].other(i)) {
				f &= !edge.inCycle;
				edge.inCycle = true;

				for (int k = i; k != j; k = inEdge[k].other(k)) {
					f &= !inEdge[k].inCycle;
					inEdge[k].inCycle = true;
				}
			}
		}
		state[i] = BLACK;
	}

	@Override
	public void validate(ValidatingScanner in) throws Exception {
		int n = in.nextInt(1, MAX_N);
		edges = new List[n];

		for (int i = 0; i < n; i++) {
			edges[i] = new ArrayList<Edge>();
		}

		TreeSet<Edge> hs = new TreeSet<Edge>();

		int m = in.nextInt(0, MAX_M);

		for (int i = 0; i < m; i++) {
			in.eoln();
			int k = in.nextInt(2, MAX_K);
			int b = in.nextInt(1, n) - 1;
			for (int j = 1; j < k; j++) {
				int e = in.nextInt(1, n) - 1;

				if (e == b) {
					throw new AssertionError(String.format(
							"There is loop in vertex %d.", e + 1));
				}

				Edge edge = new Edge(b, e);

				if (hs.contains(edge)) {
					throw new AssertionError(String.format(
							"There is multiedge between %d and %d.", b + 1,
							e + 1));
				}

				hs.add(edge);

				edges[b].add(edge);
				edges[e].add(edge);
				b = e;
			}
		}

		inEdge = new Edge[n];
		state = new int[n];

		f = false;
		dfs(0, new Edge(0, 0));

		if (f)
			throw new AssertionError("This graph isn't a cactus.");
	}
}
