1 #include<iostream>
2 #include<cmath>
3 #include<algorithm>
4 #include<vector>
5 #include<cstdio>
6 #include<cstdlib>
7 #include<queue>
8 #include<set>
9 using namespace std;
10
11 #define rhl (100000)
12 #define oo (1e5)
13 #define eps (1e-6)
14 #define maxm (8010)
15 int n,m,all,sum,tot,pos[maxm],have[maxm],cnt = 1;
16 double space[maxm]; bool exist[maxm];
17
18 inline bool equal(double x,double y) { return fabs(x-y) <= eps; }
19 inline bool dd(double a,double b) { if (equal(a,b)) return true; return a >= b; }
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
26 friend inline bool operator == (NODE p,NODE q) { return equal(p.x,q.x)&&equal(p.y,q.y); }
27 friend inline NODE operator -(NODE p,NODE q) { return (NODE) {p.x-q.x,p.y-q.y}; }
28 friend inline double operator /(NODE a,NODE b) { return a.x*b.y-b.x*a.y; }
29 inline NODE ra()
30 {
31 int xx,yy;
32 do xx = rand()%rhl,yy = rand()%rhl;
33 while (equal(1.0*xx,x)||equal(1.0*yy,y));
34 return (NODE) {1.0*xx,1.0*yy};
35 }
36 inline double angle() { return atan2(y,x); }
37 inline void read() { scanf("%lf %lf",&x,&y); }
38 }pp[maxm],army[maxm];
39
40 struct LINE
41 {
42 double a,b,c;
43 inline bool on(NODE p) { return equal(0,a*p.x+b*p.y+c); }
44 };
45
46 struct SEG
47 {
48 NODE a,b;
49 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)}; }
50 inline bool on(NODE p)
51 {
52 if (p == a) return true;
53 if (p == b) return true;
54 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)));
55 }
56 };
57
58 struct EDGE
59 {
60 int from,to,id,sur;
61
62 friend inline bool operator <(EDGE a,EDGE b) { return (pp[a.to]-pp[a.from]).angle() < (pp[b.to]-pp[b.from]).angle(); }
63 }edge[maxm];
64
65 struct SCAN
66 {
67 double x,y; int bel,sign;
68
69 friend inline bool operator <(SCAN a,SCAN b)
70 {
71 if (a.x == b.x) return a.sign > b.sign;
72 return a.x < b.x;
73 }
74 }bac[maxm];
75
76 struct SPLAY
77 {
78 int num,root,ch[maxm][2],fa[maxm],key[maxm]; queue <int> team;
79
80 inline int newnode()
81 {
82 int ret;
83 if (team.empty()) ret = ++num;
84 else ret = team.front(),team.pop();
85 fa[ret] = ch[ret][0] = ch[ret][1] = 0;
86 return ret;
87 }
88
89 inline void init()
90 {
91 num = 0; root = newnode();
92 key[root] = cnt;
93 }
94
95 inline void rotate(int x)
96 {
97 int y = fa[x],z = fa[y],l = ch[y][1] == x,r = l^1;
98 if (z != 0) ch[z][ch[z][1] == y] = x;
99 fa[x] = z; fa[y] = x; fa[ch[x][r]] = y;
100 ch[y][l] = ch[x][r]; ch[x][r] = y;
101 fa[0] = 0;
102 }
103
104 inline void splay(int x)
105 {
106 while (fa[x] != 0)
107 {
108 int y = fa[x],z = fa[y];
109 if (fa[y] != 0)
110 {
111 if ((ch[y][0] == x)^(ch[z][0] == y)) rotate(x);
112 else rotate(y);
113 }
114 rotate(x);
115 }
116 root = x;
117 }
118
119 inline int lower_bound(NODE p)
120 {
121 int now = root,ret = 0;
122 while (now)
123 {
124 int k = key[now];
125 if ((p-pp[edge[k].from])/(pp[edge[k].to]-pp[edge[k].from]) >= 0)
126 ret = k,now = ch[now][0];
127 else now = ch[now][1];
128 }
129 return ret;
130 }
131
132 inline int find(int w)
133 {
134 int now = root;
135 double x = pp[edge[w].to].x,y = pp[edge[w].to].y;
136 double ang = (pp[edge[w].to] - pp[edge[w].from]).angle();
137 while (now)
138 {
139 int k = key[now];
140 if (k == w) return now;
141 NODE p = pp[edge[k].to] - pp[edge[k].from],q = pp[edge[k].from];
142 double xx = x - q.x,yy = q.y+xx/p.x*p.y;
143 if (equal(yy,y))
144 {
145 double t = p.angle();
146 now = ch[now][ang < t];
147 }
148 else now = ch[now][y > yy];
149 }
150 }
151
152 inline void erase(int w)
153 {
154 int p = find(w);
155 while (ch[p][0] || ch[p][1])
156 {
157 if (ch[p][0])
158 {
159 rotate(ch[p][0]);
160 if (p == root) root = fa[p];
161 }
162 else
163 {
164 rotate(ch[p][1]);
165 if (p == root) root = fa[p];
166 }
167 }
168 team.push(p);
169 ch[fa[p]][ch[fa[p]][1] == p] = 0;
170 fa[p] = 0;
171 }
172
173 inline void insert(int w)
174 {
175 int now = root,pre;
176 double x = pp[edge[w].from].x,y = pp[edge[w].from].y;
177 double ang = (pp[edge[w].to] - pp[edge[w].from]).angle();
178 double xx,yy;
179 while (true)
180 {
181 int k = key[now];
182 NODE p = pp[edge[k].to] - pp[edge[k].from],q = pp[edge[k].from];
183 xx = x - q.x,yy = q.y+xx/p.x*p.y;
184 if (equal(yy,y))
185 {
186 double t = p.angle();
187 pre = now,now = ch[now][ang > t];
188 if (!now)
189 {
190 now = newnode(); fa[now] = pre;
191 ch[pre][ang > t] = now; key[now] = w;
192 break;
193 }
194 }
195 else
196 {
197 pre = now,now = ch[now][y > yy];
198 if (!now)
199 {
200 now = newnode(); fa[now] = pre;
201 ch[pre][y>yy] = now; key[now] = w;
202 break;
203 }
204 }
205 }
206 splay(now);
207 }
208 }S;
209 vector <int> G[maxm],sp[maxm],ss[maxm],ans;
210 set <int> con[maxm];
211
212 inline void add(int a,int b)
213 {
214 ++cnt; G[a].push_back(cnt);
215 edge[cnt] = (EDGE) {a,b};
216 }
217
218 inline int find(NODE p)
219 {
220 for (int i = 1;i <= all;++i) if (pp[i] == p) return i;
221 pp[++all] = p; return all;
222 }
223
224 inline bool cmp(int a,int b) { return edge[a] < edge[b]; }
225
226 inline NODE cp(LINE l1,LINE l2)
227 {
228 double a1 = l1.a,b1 = l1.b,c1 = l1.c;
229 double a2 = l2.a,b2 = l2.b,c2 = l2.c;
230 double ry = (c2*a1-c1*a2)/(b1*a2-b2*a1),rx = (c1*b2-c2*b1)/(b1*a2-b2*a1);
231 return (NODE) {rx,ry};
232 }
233
234 inline bool para(LINE l1,LINE l2) { return equal(l1.a * l2.b,l1.b * l2.a); }
235
236 inline bool okay(int a,int b)
237 {
238 int nn2 = sp[b].size(),nn1 = sp[a].size(),cro;
239 NODE p,q; SEG s,t; LINE l,l1;
240 for (int i = 0;i < nn2;++i)
241 {
242 p = pp[sp[b][i]]; q = p.ra();
243 s = (SEG) {p,q}; l = s.extend();
244 cro = 0;
245 for (int j = 0;j < nn1;++j)
246 {
247 t = (SEG) {pp[sp[a][j]],pp[sp[a][(j+1)%nn1]]};
248 l1 = t.extend();
249 if (l1.on(p)&&t.on(p)) return false;
250 if (para(l,l1)) continue;
251 q = cp(l,l1);
252 if (dd(q.x,p.x)&&t.on(q)) ++cro;
253 }
254 if (!(cro&1)) return false;
255 }
256 return true;
257 }
258
259 inline void find_surface()
260 {
261 for (int i = 1;i <= all;++i) sort(G[i].begin(),G[i].end(),cmp);
262 for (int i = 1;i <= all;++i)
263 {
264 int nn = G[i].size();
265 for (int j = 0;j < nn;++j) edge[G[i][j]].id = j;
266 }
267 for (int i = 2;i <= cnt;++i)
268 if (!edge[i].sur)
269 {
270 ++tot; int j = i,p,nn; double res = 0;
271 while (!edge[j].sur)
272 {
273 edge[j].sur = tot; p = edge[j].to;
274 sp[tot].push_back(p); ss[tot].push_back(j);
275 j ^= 1; nn = G[p].size();
276 j = G[p][(edge[j].id+1)%nn];
277 }
278 nn = sp[tot].size();
279 for (j = 0;j < nn;++j)
280 res += (pp[sp[tot][j]]-pp[sp[tot][0]])/(pp[sp[tot][(j+1)%nn]]-pp[sp[tot][0]]);
281 res /= 2; space[tot] = res;
282 }
283 space[0] = -1e12;
284 for (int i = 1;i <= tot;++i)
285 if (!exist[i]&&space[i] > 0)
286 {
287 int in = 0;
288 for (int j = 1;j <= tot;++j)
289 if (!exist[j]&&space[j]<0&&space[j]>space[in])
290 if (okay(j,i)) in = j;
291 if (in)
292 {
293 exist[i] = true;
294 int nn = ss[i].size();
295 for (int j = 0;j < nn;++j) edge[ss[i][j]].sur = in;
296 }
297 }
298 for (int i = 2;i <= cnt;i += 2)
299 {
300 if (space[edge[i].sur] <= 0&&space[edge[i^1].sur] <= 0)
301 {
302 con[edge[i].sur].insert(edge[i^1].sur);
303 con[edge[i^1].sur].insert(edge[i].sur);
304 }
305 }
306 }
307
308 inline void locate()
309 {
310 for (int i = 1;i <= n;++i)
311 bac[++sum] = (SCAN) { army[i].x,army[i].y,i,0 };
312 for (int i = 2;i <= cnt;i += 2)
313 {
314 if (equal(pp[edge[i].from].x,pp[edge[i].to].x)) continue;
315 bac[++sum] = (SCAN) { pp[edge[i].from].x,pp[edge[i].from].y,i,1 };
316 bac[++sum] = (SCAN) { pp[edge[i].to].x,pp[edge[i].to].y,i,2 };
317 }
318 pp[++all] = (NODE) {-oo,-oo}; pp[++all] = (NODE) {oo,-oo};
319 edge[++cnt] = (EDGE) {all-1,all};
320 sort(bac+1,bac+sum+1);
321 S.init();
322 for (int i = 1;i <= sum;++i)
323 {
324 if (bac[i].sign == 0) pos[bac[i].bel] = edge[S.lower_bound((NODE) {bac[i].x,bac[i].y})].sur;
325 else if (bac[i].sign == 1) S.insert(bac[i].bel);
326 else S.erase(bac[i].bel);
327 }
328 }
329
330 inline void solve()
331 {
332 for (int i = 1;i <= n;++i) have[pos[i]] = i;
333 for (int i = 1;i <= n;++i)
334 {
335 ans.clear();
336 set <int> :: iterator it;
337 for (it = con[pos[i]].begin();it != con[pos[i]].end();++it)
338 ans.push_back(have[*it]);
339 sort(ans.begin(),ans.end());
340 int nn = ans.size();
341 printf("%d",nn);
342 for (int j = 0;j < nn;++j) printf(" %d",ans[j]);
343 putchar(‘\n‘);
344 }
345 }
346
347 int main()
348 {
349 freopen("1035.in","r",stdin);
350 freopen("1035.out","w",stdout);
351 srand(233);
352 scanf("%d %d",&n,&m);
353 for (int i = 1;i <= n;++i) army[i].read();
354 for (int i = 1;i <= m;++i)
355 {
356 NODE p,q; p.read(); q.read();
357 int a = find(p),b = find(q);
358 if (p.x > q.x) swap(a,b);
359 add(a,b); add(b,a);
360 }
361 find_surface();
362 locate();
363 solve();
364 fclose(stdin); fclose(stdout);
365 return 0;
366 }