/*--------------------------------------------------------------*/
/* ACM ICPC 2007-2008                                           */
/* Northeastern European Regional Contest                       */
/* St Petersburg - Barnaul - Tashkent - Batumi, November 28, 200*/
/*--------------------------------------------------------------*/
/* Problem C. Cactus Reloaded                                   */
/*--------------------------------------------------------------*/
/* Solution                                                     */
/*                                                              */
/* Author                Roman Satyukov                         */
/*--------------------------------------------------------------*/
 
import java.util.*;
import java.io.*;

public class cactus_rs implements Runnable {
	private BufferedReader in;
	private PrintWriter out;
	
    class MyTreeSet {
        private TreeMap<Integer, Integer> tree;
        
        public MyTreeSet() {
        	this.tree = new TreeMap<Integer, Integer>();
        }

        public void add(int u) {
        	if (tree.containsKey(u)) {
        		tree.put(u, tree.get(u) + 1);
        	} else {
        		tree.put(u, 1);
        	}
        }

        public void remove(int u) {
        	int newValue = tree.get(u) - 1;
        	if (newValue == 0) {
        		tree.remove(u);
        	} else {
        		tree.put(u, newValue);
        	}
        }
        
        public int getMax() {
        	return tree.lastKey();
        }

        public void clear() {
            tree.clear();
        }
    }
    
	private class Graph {
		private int n, ans;
		private int[] head;
		private int[] next;
		private int[] target;
		private int[] stack;
		private int[] dfsColour;
		private boolean[] edgeMark;
		private ArrayList<Integer>[] cycles;
		private ArrayList<Integer>[] vertexCycles;
		private int sp, edges;
		private int curCycleColour;
		private MyTreeSet mySet;
		
		@SuppressWarnings("unchecked")
		public Graph(int n, int m) {
			this.n = n;
			this.head = new int[n];
			this.next = new int[2 * m];
			this.target = new int[2 * m];
			this.stack = new int[n];
			this.dfsColour = new int[n];
			this.cycles = new ArrayList[n];
			this.vertexCycles = new ArrayList[n];
			this.edgeMark = new boolean[2 * m];
			for (int i = 0; i < cycles.length; i++) {
				cycles[i] = new ArrayList<Integer>();
				vertexCycles[i] = new ArrayList<Integer>();
			}
			this.edges = 0;
			Arrays.fill(head, -1);
		}
		
		public void addEdge(int u, int v) {
			target[edges] = v;
			next[edges] = head[u];
			head[u] = edges++;
			
			target[edges] = u;
			next[edges] = head[v];
			head[v] = edges++;
		}
		
		private void add2cycle(int u) {
			vertexCycles[u].add(curCycleColour);
			cycles[curCycleColour].add(u);
		}

		private void dfs1(int u, int p) {
			dfsColour[u] = 1;
			for (int e = head[u]; e != -1; e = next[e]) {
				int v = target[e];
				if (v == p || dfsColour[v] == 2) {
					continue;
				}
				if (dfsColour[v] == 1) {
					for (int i = sp - 1; i >= 0; i--) {
						int cur = target[stack[i]];
						if (cur == v) {
							break;
						}
						edgeMark[stack[i]] = true;
						add2cycle(cur);
					}
					edgeMark[e] = true;
					add2cycle(v);
					curCycleColour++;
					continue;
				}
				stack[sp++] = e;
				dfs1(v, u);
				sp--;
			}
			dfsColour[u] = 2;
		}
		
		private int calc1(int u, int cycle) {
			int res = 0;
			int max1 = -1000000000;
			int max2 = -1000000000;
			for (int c: vertexCycles[u]) {
				if (c != cycle) {
					int cur = calc2(u, c);
					if (cur > max1) {
						max2 = max1;
						max1 = cur;
					} else if (cur > max2) {
						max2 = cur;
					}
					res = Math.max(res, cur);
				}
			}
			ans = Math.max(ans, max1 + max2);
			return res;
		}

		private int calc2(int u, int cycle) {
			int sz = cycles[cycle].size();
			int[] tmp = new int[sz];
			int pos = -1;
			for (int i = 0; i < sz; i++) {
				int v = cycles[cycle].get(i);
				if (v == u) {
					pos = i;
					tmp[i] = -1000000000;
					continue;
				}
				tmp[i] = calc1(v, cycle);
			}
			
			if (sz == 2) {
				ans = Math.max(ans, tmp[0] + tmp[1] + 1);
			} else {
				mySet.clear();
				for (int i = 1; i <= sz / 2; i++) {
					mySet.add(tmp[i] + i);
				}
				for (int i = 0; i < sz; i++) {
					int j = i + sz / 2;
					int max = mySet.getMax();
					ans = Math.max(ans, max - i + tmp[i]);
					mySet.remove(tmp[(i + 1) % sz] + i + 1);
					mySet.add(tmp[(j + 1) % sz] + j + 1);
				}
			}
//			for (int i = 0; i < sz; i++) {
//				for (int j = 0; j < sz; j++) {
//					if (i == j) {
//						continue;
//					}
//					int dist = Math.abs(i - j);
//					dist = Math.min(dist, sz - dist);
//					ans = Math.max(ans, tmp[i] + tmp[j] + dist);
//				}
//				ans = Math.max(ans,  tmp[i]);
//			}
	        
			if (pos == -1) {
				return 0;
			}
			int res = 0;
			for (int j = 0; j < sz; j++) {
				int dist = Math.abs(pos - j);
				dist = Math.min(dist, sz - dist);
				res = Math.max(res, dist + tmp[j]);
			}
			return res;
		}
		
		public int diameter() {
			stack = new int[n];
			sp = 0;
			curCycleColour = 0;
			Arrays.fill(dfsColour, 0);
			dfs1(0, -1);
			for (int i = 0; i < edges; i++) {
				if (!edgeMark[i] && !edgeMark[i ^ 1]) {
					edgeMark[i] = true;
					add2cycle(target[i]);
					add2cycle(target[i ^ 1]);
					curCycleColour++;
				}
			}
			
			mySet = new MyTreeSet();
			if (curCycleColour > 0) {
				calc2(-1, 0);
			}
			return ans;
		}
	}
	
	private void solve() throws IOException {
		StringTokenizer st = new StringTokenizer(in.readLine());
		int n = Integer.parseInt(st.nextToken());
		int k = Integer.parseInt(st.nextToken());
		int[][] tmp = new int[k][];
		int edges = 0;
		for (int i = 0; i < k; i++) {
			st = new StringTokenizer(in.readLine());
			int m = Integer.parseInt(st.nextToken());
			tmp[i] = new int[m];
			edges += m;
			for (int j = 0; j < m; j++) {
				tmp[i][j] = Integer.parseInt(st.nextToken()) - 1;
			}
		}
		Graph g = new Graph(n, edges);
		for (int i = 0; i < k; i++) {
			for (int j = 0; j < tmp[i].length - 1; j++) {
				g.addEdge(tmp[i][j], tmp[i][j + 1]);
			}
		}
		out.println(g.diameter());
	}
	
	public static void main(String[] args) {
		new Thread(new cactus_rs()).start();
	}

	public void run() {
		String problem = getClass().getName().split("_")[0];
		try {
			in = new BufferedReader(new StreamReader(System.in));
			out = new PrintWriter(System.out);
			solve();
			in.close();
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
			System.exit(1);
		}
	}
}
