1 #include<algorithm>
2 #include<cmath>
3 #include<queue>
4 #include<cstdio>
5 #include<cstdlib>
6 #include<iostream>
7 using namespace std;
8
9 #define rhl 10001
10 #define esp (1e-4)
11 #define maxn (30)
12 #define maxc (30)
13 #define maxm (40)
14 int tot,n,c,have[maxc]; double ans;
15
16 inline double equal(double a,double b) { return fabs(a-b) < esp; }
17
18 inline bool dd(double a,double b) { if (equal(a,b)) return true; return a >= b; } //>=
19
20 inline bool xd(double a,double b) { if (equal(a,b)) return true; return a <= b; } //<=
21
22 struct NODE
23 {
24 double x,y;
25 friend inline bool operator == (NODE a,NODE b) { return equal(a.x,b.x)&&equal(a.y,b.y); }
26 friend inline bool operator < (NODE a,NODE b)
27 {
28 if (a.x != b.x) return a.x < b.x;
29 else return a.y < b.y;
30 }
31 inline NODE ra()
32 {
33 int xx,yy;
34 do xx = rand()%rhl,yy = rand()%rhl;
35 while (equal(1.0*xx,x)||equal(1.0*yy,y));
36 return (NODE) {1.0*xx,1.0*yy};
37 }
38 inline void read() { scanf("%lf %lf",&x,&y); }
39 }pol[maxc][maxm],bac[maxc*maxm];
40 struct LINE
41 {
42 double a,b,c;
43 friend inline bool operator ==(LINE l1,LINE l2) { return equal(l1.a*l2.c,l2.a*l1.c); }
44 inline LINE vert(NODE p) { return (LINE) {b,-a,a*p.y-b*p.x}; }
45 inline bool on(NODE p) { return equal(0,a*p.x+b*p.y+c); }
46 };
47 struct SEG{
48 NODE a,b;
49 inline NODE MID() { return (NODE) {(a.x+b.x)/2,(a.y + b.y)/2}; }
50 inline bool exist() { return !(a == b); }
51 inline LINE extend() { return (LINE) {a.y-b.y,b.x-a.x,b.y*(a.x-b.x)-b.x*(a.y-b.y)}; }
52 inline bool on(NODE p)
53 {
54 if (p == a) return true;
55 if (p == b) return true;
56 return (dd(p.x,min(a.x,b.x))&xd(p.x,max(a.x,b.x)))&&(dd(p.y,min(a.y,b.y))&xd(p.y,max(a.y,b.y)));
57 }
58 }temp[maxn];
59 queue <SEG> team;
60
61 inline bool para(LINE l1,LINE l2) { return equal(l1.a * l2.b,l1.b * l2.a); }
62
63 inline double qua(double a) { return a * a; }
64
65 inline double dis(NODE a,NODE b) { return sqrt(qua(a.x - b.x)+qua(a.y - b.y)); }
66
67 inline NODE cp(LINE l1,LINE l2)
68 {
69 double a1 = l1.a,b1 = l1.b,c1 = l1.c;
70 double a2 = l2.a,b2 = l2.b,c2 = l2.c;
71 double ry = (c2*a1-c1*a2)/(b1*a2-b2*a1),rx = (c1*b2-c2*b1)/(b1*a2-b2*a1);
72 return (NODE) {rx,ry};
73 }
74
75 inline void cross(SEG s,int now)
76 {
77 LINE l = s.extend(),l1; SEG t; NODE p; NODE tt[maxm];
78 int cnt = 0;
79 for (int i = 1;i <= have[now];++i)
80 {
81 t = (SEG) {pol[now][i],pol[now][i-1]};
82 l1 = t.extend();
83 if (para(l,l1))
84 {
85 if (l == l1)
86 {
87 if (s.on(t.a)) tt[++cnt] = t.a;
88 if (s.on(t.b)) tt[++cnt] = t.b;
89 }
90 continue;
91 }
92 p = cp(l,l1);
93 if (t.on(p) && s.on(p))
94 tt[++cnt] = p;
95 }
96 sort(tt+1,tt+cnt+1);
97 for (int i = 1;i <= cnt;++i) bac[++tot] = tt[i];
98 }
99
100 inline NODE find(NODE p)
101 {
102 NODE ret,q; LINE l1,l2; SEG s; double best = 1e9,len;
103 for (int i = 1;i <= c;++i)
104 for (int j = 1;j <= have[i];++j)
105 {
106 s = (SEG) {pol[i][j],pol[i][j-1]};
107 l1 = s.extend();
108 l2 = l1.vert(p);
109 q = cp(l1,l2);
110 if (s.on(q))
111 {
112 len = dis(p,q);
113 if (best > len) ret = q,best = len;
114 }
115 else
116 {
117 if (dis(p,s.a) < dis(p,s.b)) q = s.a;
118 else q = s.b;
119 len = dis(p,q);
120 if (best > len) ret = q,best = len;
121 }
122 }
123 return ret;
124 }
125
126 inline bool in(NODE p)
127 {
128 NODE q = p.ra(); SEG s = (SEG) {p,q},t; LINE l = s.extend(),l1; int cnt;
129 for (int i = 1;i <= c;++i)
130 {
131 cnt = 0;
132 for (int j = 1;j <= have[i];++j)
133 {
134 t = (SEG) {pol[i][j],pol[i][j-1]};
135 if ((t.extend()).on(p)&&t.on(p)) return false;
136 l1 = t.extend();
137 if (para(l,l1)) continue;
138 q = cp(l,l1);
139 if (dd(q.x,p.x)&&t.on(q)) ++cnt;
140 }
141 if (cnt & 1) return true;
142 }
143 return false;
144 }
145
146 inline void init()
147 {
148 for (int i = 1;i < n;++i)
149 {
150 tot = 0;
151 if (!(temp[i].a < temp[i].b)) swap(temp[i].a,temp[i].b);
152 for (int j = 1;j <= c;++j)
153 cross(temp[i],j);
154 if (!in(temp[i].a)) bac[++tot] = temp[i].a;
155 if (!in(temp[i].b)) bac[++tot] = temp[i].b;
156 sort(bac+1,bac+tot+1);
157 for (int j = 1;j < tot;j++)
158 if (!in((SEG){bac[j],bac[j+1]}.MID()))
159 team.push((SEG){bac[j],bac[j+1]});
160 }
161 }
162
163 inline void work()
164 {
165 SEG now; NODE mid,p1,p2,l,r; double ret;
166 while (!team.empty())
167 {
168 now = team.front(); team.pop();
169 if (!now.exist()) continue;
170 p1 = find(now.a); p2 = find(now.b);
171 l = now.a,r = now.b;
172 while (!(l == r))
173 {
174 mid = ((SEG){l,r}).MID();
175 if (dis(p1,mid) > dis(p2,mid)) r = mid;
176 else l = mid;
177 }
178 ret = dis(r,p1);
179 ans = max(max(dis(now.a,p1),dis(now.b,p2)),ans);
180 if (ret-esp < ans) continue;
181 mid = now.MID();
182 team.push((SEG){now.a,mid}),team.push((SEG){mid,now.b});
183 }
184 }
185
186 int main()
187 {
188 srand(233);
189 ans = 0;
190 scanf("%d %d ",&c,&n);
191 NODE p1,p2; p1.read();
192 for (int i = 2;i <= n;++i)
193 {
194 p2.read(); temp[i-1] = (SEG) {p1,p2};
195 p1 = p2;
196 }
197 for (int i = 1;i <= c;++i)
198 {
199 scanf("%d ",have+i);
200 for (int j = 1;j <= have[i];++j) pol[i][j].read();
201 pol[i][0] = pol[i][have[i]];
202 }
203 init();
204 work();
205 printf("%.2lf\n",ans);
206 fclose(stdin); fclose(stdout);
207 return 0;
208 }