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

public class cactus_gk_nlogn implements Runnable {
    private StreamTokenizer t;

    private int nextInt() throws IOException {
        t.nextToken();
        return (int) t.nval;
    }

    private static class Edge {
        private final int v1;
        private final int v2;

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

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

    private static class Result {
        final int v;
        final int max;
        final int length;
        final List<Result> cycle;

        public Result(int v, int max, int length, List<Result> cycle) {
            this.v = v;
            this.max = max;
            this.length = length;
            this.cycle = cycle;
        }

        @Override
        public String toString() {
            return (v + 1) + "(" + max + ", " + length + ") ";
        }
    }

    private List<List<Edge>> edges;
    private int color[];

    class Entry implements Comparable<Entry> {
        final int index;
        final int length;

        public Entry(int index, int length) {
            this.index = index;
            this.length = length;
        }

        public int compareTo(Entry that) {
            return that.length - this.length;
        }
    }
    
    public Result processCycle(int v, List<Result> results) {
        int n = results.size();

        int length = 0;
        int max = 0;
        for (int i = 1; i < n; i++) {
            int d = Math.min(i, n - i);
            Result result = results.get(i);
            length = Math.max(length, result.length + d);
            max = Math.max(max, result.max);
        }
        
        max = Math.max(max, length);
        Queue<Entry> heap = new PriorityQueue<Entry>();
        for (int i = 0; i < 2 * n; i++) {
            int l = results.get(i % n).length;
            while (!heap.isEmpty() && (i - heap.peek().index) * 2 > n) {
                heap.remove();
            }
            if (!heap.isEmpty()) {
                max = Math.max(max, l + heap.peek().length + i);
            }
            heap.offer(new Entry(i, l - i));
        }

        Result result = new Result(v, max, length, null);
        /*
        System.out.print("processCycle:");
        for (Result r : results) {
            System.out.print(r);
        }
        System.out.println(": " + result);
        */
        return result;
    }

    public class Maximizer {
        int max1;
        int max2;

        public void update(int result) {
            if (result > max1) {
                max2 = max1;
                max1 = result;
            } else if (result > max2) {
                max2 = result;
            }
        }
    }

    Result dfs(int v, int parent) {
        color[v] = 1;

        Maximizer maximizer = new Maximizer();
        List<Result> cycle = null;
        int max = 0;
        for (Edge e: edges.get(v)) {
            int v2 = e.other(v);
            if (color[v2] == 0) {
                Result result = dfs(v2, v);
                if (result.cycle != null) {
                    if (result.cycle.get(0).v == v) {
                        result = processCycle(v, result.cycle);
                        maximizer.update(result.length);
                        max = Math.max(max, result.max);
                    } else {
                        cycle = result.cycle;
                    }
                } else {
                    maximizer.update(result.length + 1);
                    max = Math.max(max, result.max);
                }
            } else if (v2 != parent && color[v2] == 1) {
                cycle = new ArrayList<Result>();
                //System.out.println("startCycle " + (v2 + 1));
                cycle.add(new Result(v2, 0, 0, cycle));
            }
        }


        int length = maximizer.max1;
        max = Math.max(max, length + maximizer.max2); 

        color[v] = 2;
        
        Result result = new Result(v, max, length, cycle);
        if (cycle != null) {
            cycle.add(result);
        }
        //System.out.println(result + " " + results);
        return result;
    }

    public void run() {
        try {
            Locale.setDefault(Locale.US);

            t = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));

            int n = nextInt();

            edges = new ArrayList<List<Edge>>();
            for (int i = 0; i < n; i++) {
                edges.add(new ArrayList<Edge>());
            }

            int m = nextInt();
            for (int i = 0; i < m; i++) {
                int l = nextInt();
                int b = nextInt() - 1;
                for (int j = 1; j < l; j++) {
                    int e = nextInt() - 1;
                    Edge edge = new Edge(b, e);
                    edges.get(b).add(edge);
                    edges.get(e).add(edge);
                    b = e;
                }
            }

            color = new int[n];
            int diameter = 0;
            for (int i = 0; i < n; i++) {
                if (color[i] == 0) {
                    diameter = Math.max(diameter, dfs(i, -1).max);
                }
            }

            PrintWriter out = new PrintWriter(System.out);
            out.println(diameter);
            out.close();
        } catch (IOException e) {
        }
    }

    public static void main(String[] args) {
        new Thread(new cactus_gk_nlogn()).start();
    }
}
