1 #include <cstdio>
2 #include <cstring>
3 #include <cstdlib>
4 #include <cmath>
5 #include <deque>
6 #include <vector>
7 #include <queue>
8 #include <iostream>
9 #include <algorithm>
10 #include <map>
11 #include <set>
12 #include <ctime>
13 using namespace std;
14 typedef long long LL;
15 typedef double DB;
16 #define For(i, s, t) for(int i = (s); i <= (t); i++)
17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--)
18 #define Rep(i, t) for(int i = (0); i < (t); i++)
19 #define Repn(i, t) for(int i = ((t)-1); i >= (0); i--)
20 #define rep(i, x, t) for(int i = (x); i < (t); i++)
21 #define MIT (2147483647)
22 #define INF (1000000001)
23 #define MLL (1000000000000000001LL)
24 #define sz(x) ((int) (x).size())
25 #define clr(x, y) memset(x, y, sizeof(x))
26 #define puf push_front
27 #define pub push_back
28 #define pof pop_front
29 #define pob pop_back
30 #define ft first
31 #define sd second
32 #define mk make_pair
33 inline void SetIO(string Name) {
34 string Input = Name+".in",
35 Output = Name+".out";
36 freopen(Input.c_str(), "r", stdin),
37 freopen(Output.c_str(), "w", stdout);
38 }
39
40 const int N = 50010, M = 200010;
41 int First[N], To[M], Next[M], Tot;
42 int n, m;
43 int Circle[2*N], Scir, Len;
44 int Dfn[N], Low[N], Tag, WhoVisit[N];
45 int Dp[N], Ans;
46
47 inline void Insert(int u, int v) {
48 Tot++;
49 To[Tot] = v, Next[Tot] = First[u];
50 First[u] = Tot;
51 }
52
53 inline void Input() {
54 scanf("%d%d", &n, &m);
55 For(i, 1, m) {
56 int l, u, v;
57 scanf("%d%d", &l, &u);
58 l--;
59 while(l--) {
60 scanf("%d", &v);
61 Insert(u, v), Insert(v, u);
62 u = v;
63 }
64 }
65 }
66
67 int Que[N];
68 inline void Work() {
69 For(i, 1, Scir) Circle[Scir+i] = Circle[i];
70 int Head, Tail, x;
71 Head = Tail = 1, Que[1] = 1;
72 For(i, 2, Scir*2) {
73 x = Circle[i];
74 while(Head <= Tail && i-Que[Head] > Scir/2) Head++;
75 if(Head <= Tail) Ans = max(Ans, Dp[x]+i+Dp[Circle[Que[Head]]]-Que[Head]);
76 while(Head <= Tail && Dp[Que[Tail]]-Que[Tail] <= Dp[x]-i) Tail--;
77 Que[++Tail] = i;
78 }
79 }
80
81 inline void Updata(int &A, int &B, int C) {
82 if(A < C) {
83 B = A;
84 A = C;
85 } else if(B < C) B = C;
86 }
87
88 typedef pair<int, int> State;
89 State Stack[N];
90 int top, Sta[N], Size, Cnt[N];
91 bool EverCircle[N];
92 inline void Tarjan() {
93 Stack[1] = State(1, 0), top = 1, Tag = 0, Size = 1, Sta[1] = 1;
94 while(top) {
95 int u = Stack[top].ft, fa = Stack[top].sd;
96 if(!Dfn[u]) Dfn[u] = Low[u] = ++Tag, EverCircle[u] = 0, Cnt[u] = 0;
97
98 bool Finish = 1, GoOn = 0;
99 int Tab = First[u], v;
100 if(Tab) {
101 if((v = To[Tab]) != fa) {
102 if(!Dfn[v]) {
103 Stack[++top] = State(v, u), Sta[++Size] = v;
104 WhoVisit[v] = u;
105 GoOn = 1;
106 } else if(WhoVisit[v] == u) {
107 Low[u] = min(Low[u], Low[v]);
108 if(Low[v] > Dfn[u]) {
109 Size--;
110 Updata(Dp[u], Cnt[u], Dp[v]+1);
111 } else if(Low[v] == Dfn[u]) {
112 for(Scir = 0; Sta[Size] != u; Circle[++Scir] = Sta[Size--]);
113 Circle[++Scir] = u;
114 Work();
115 int Dis = 0;
116 Ford(i, Scir-1, 1) Dis = max(Dis, Dp[Circle[i]]+min(i, Scir-i));
117 Updata(Dp[u], Cnt[u], Dis);
118 }
119 } else Low[u] = min(Low[u], Dfn[v]);
120 }
121 Finish = 0;
122 }
123
124 if(GoOn) continue;
125 if(!Finish) {
126 First[u] = Next[First[u]];
127 continue;
128 }
129 Stack[top--] = State(0, 0);
130 //Ans = max(Ans, Dp[u]+Cnt[u]);
131 if(Ans < Dp[u]+Cnt[u]) {
132 Ans = Dp[u]+Cnt[u];
133 //printf("Ans: %d Id: %d\n", Ans, u);
134 }
135 }
136 }
137
138 inline void Solve() {
139 Tarjan();
140
141 printf("%d\n", Ans);
142 }
143
144 int main() {
145 SetIO("cactus");
146 Input();
147 Solve();
148 return 0;
149 }