import std.algorithm;
import std.array;
import std.ascii;
import std.container;
import std.conv;
import std.math;
import std.numeric;
import std.range;
import std.stdio;
import std.string;
import std.typecons;

void log(A...)(A arg) {
    stderr.writeln(arg);
}
int size(T)(in T s) {
    return cast(int)s.length;
}

immutable real EPS = 1e-7;

struct Point {
    real x, y;
    Point opBinary(string op)(in Point p) const if (op == "+" || op == "-") {
        return Point(mixin("x" ~ op ~ "p.x"), mixin("y" ~ op ~ "p.y"));
    }
    Point opBinary(string op)(real k) const if (op == "*" || op == "/") {
        return Point(mixin("x" ~ op ~ "k"), mixin("y" ~ op ~ "k"));
    }
};
real dot(in Point a, in Point b) { return a.x * b.x + a.y * b.y; }
real cross(in Point a, in Point b) { return a.x * b.y - a.y * b.x; }
real norm(in Point a) { return sqrt(dot(a, a)); }
Point rot90(in Point p) { return Point(-p.y, p.x); }
real angle(in Point a) { return atan2(a.y, a.x); }

int ccw(Point a, Point b, Point c){
    b = b - a; c = c - a;
    if (cross(b, c) > EPS) return +1; 
    if (cross(b, c) < -EPS) return -1;
    if (dot(b, c) < 0) return +2;     
    if (norm(b) < norm(c)) return -2; 
    return 0;                         
}

struct Segment {
    Point a, b;
};
bool intersects(in Segment s, in Segment t) {
    // endpoint exclusive
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) < 0 && ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) < 0;
}

struct Line {
    Point a, b;
};
bool contains(in Line l, in Point p) { return ccw(l.a, l.b, p) % 2 == 0; }
bool parallel(in Line s, in Line t) { return abs(cross(s.b - s.a, t.b - t.a)) < EPS; }
bool orthogonal(in Line s, in Line t) { return abs(dot(s.b - s.a, t.b - t.a)) < EPS; }
bool equals(in Line s, in Line t) { return parallel(s, t) && contains(s, t.a); }
Point crosspoint(in Line s, in Line t) {
    real d = cross(t.b - t.a, s.b - s.a);
    assert(abs(d) >= EPS);
    return s.a + (s.b - s.a) * cross(t.b - t.a, t.b - s.a) / d;
}

void main() {
    int N, M; readf("%s %s\n", &N, &M);
    Point[][] P = new Point[][N];
    foreach (i; 0 .. N) {
        int L; readf("%s\n", &L);
        P[i] = new Point[L];
        foreach (ref p; P[i]) {
            readf("%s %s\n", &p.x, &p.y);
        }
    }
    Point[] X = new Point[M];
    foreach (ref p; X) {
        readf("%s %s\n", &p.x, &p.y);
    }

    //log(X);

    Line[] ls;
    foreach (x; X) {
        foreach (ps; P) {
            foreach (p; ps) {
                ls ~= Line(x, p);
            }
        }
    }
    //log(ls);
    Point[] cands;
    foreach (i, l; ls) {
        foreach (j, m; ls[i + 1 .. $]) {
            if (parallel(l, m)) continue;
            cands ~= crosspoint(l, m);
        }
    }

    int count(in Point z) { // how many voters can see the candidate standing at z
        int ans = 0;
        foreach (x; X) {
            auto s = Segment(z, x);
            foreach (ps; P) {
                int N = ps.size;
                foreach (i; 0 .. N) {
                    auto t = Segment(ps[i], ps[(i + 1) % N]);
                    if (s.intersects(t)) goto next; // voter at x cannot see the candidate
                }
            }
            ans++;
            next:;
        }
        return ans;
    }
    int ans = 0;
    foreach (z; cands) {
        ans = max(ans, count(z));
    }
    writeln(ans);
}

Measured memory_bytes: 2736