#include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



struct Point{
	Point(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}

	Point(){
		x = y = 0.0;
	}

	Point operator + (Point p){ return Point(x+p.x,y+p.y); }
	Point operator - (Point p){ return Point(x-p.x,y-p.y);}
	Point operator * (double a){ return Point(a*x,a*y); }
	Point operator / (double a){ return Point(x/a,y/a); }

	double abs(){ return sqrt(norm()); }
	double norm(){ return x*x + y*y; }

	bool operator<(const Point &p) const{
		return x != p.x? x < p.x: y < p.y;
	}

	bool operator == (const Point &p) const{
		return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS;
	}

	double x,y;
};

struct Line{
public:
	Point p[2];
	Line(Point p1,Point p2){
		p[0] = p1;
		p[1] = p2;
	}
	Line(){

	}
};

typedef Point Vector;
typedef vector<Point> Polygon;

int num_polygon,num_human;
vector<Point> HUMAN,CANDIDATE;
vector<Line> LINE;
vector<Polygon> POLYGON;

//交点を求める関数
Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

//インタフェース関数
Point calc_Cross_Point(Point a,Point b,Point c,Point d){
	return calc_Cross_Point(a.x,b.x,c.x,d.x,a.y,b.y,c.y,d.y);
}

int func(double x1,double y1,double x2, double y2, double xp, double yp){
	double naiseki,norm1,norm2,gaiseki;
	norm1 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
	norm2 = sqrt((xp-x1)*(xp-x1)+(yp-y1)*(yp-y1));
	naiseki = (xp-x1)*(x2-x1)+(yp-y1)*(y2-y1);
	gaiseki = (x2-x1)*(yp-y1)-(xp-x1)*(y2-y1);
	if(gaiseki > EPS){
		return 1;
	}else if(gaiseki < -EPS){
		return -1;
	}
	if(naiseki < -EPS){
		return 2;
	}

	if(norm1 < norm2){
		return -2;
	}
	return 0;
}

bool is_Cross(Line a,Line b){

	if(func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[0].x,b.p[0].y)*
			func(a.p[0].x,a.p[0].y,a.p[1].x,a.p[1].y,b.p[1].x,b.p[1].y) <= 0 &&
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[0].x,a.p[0].y)*
			func(b.p[0].x,b.p[0].y,b.p[1].x,b.p[1].y,a.p[1].x,a.p[1].y) <= 0){
		return true;
	}
	return false;
}


int main(){

	scanf("%d %d",&num_polygon,&num_human);

	int num;

	for(int i = 0; i < num_polygon; i++){

		Polygon polygon;

		scanf("%d",&num);

		for(int k = 0; k < num; k++){

			Point tmp_point;

			scanf("%lf %lf",&tmp_point.x,&tmp_point.y);
			polygon.push_back(tmp_point);
		}
		POLYGON.push_back(polygon);
	}

	for(int i = 0; i < num_human; i++){

		Point tmp_point;

		scanf("%lf %lf",&tmp_point.x,&tmp_point.y);

		HUMAN.push_back(tmp_point);
	}

	//各有権者と、ポリゴンの頂点を結ぶ線分を求める
	for(int i = 0; i < num_human; i++){ //10
		for(int k = 0; k < num_polygon; k++){ //5
			for(int a = 0; a < POLYGON[k].size(); a++){ //15

				Line tmp_line;

				tmp_line.p[0] = HUMAN[i];
				tmp_line.p[1] = Point(HUMAN[i].x+100*(POLYGON[k][a].x-HUMAN[i].x),
								HUMAN[i].y+100*(POLYGON[k][a].y-HUMAN[i].y)); //線分をポリゴン方向に伸ばす

				LINE.push_back(tmp_line);
			}
		}
	}


	//候補となる点を列挙する
	for(int i = 0; i < LINE.size()-1; i++){
		for(int k = i+1; k < LINE.size(); k++){
			if(!is_Cross(LINE[i],LINE[k]))continue;

			CANDIDATE.push_back(calc_Cross_Point(LINE[i].p[0],LINE[i].p[1],LINE[k].p[0],LINE[k].p[1]));
		}
	}

	//候補点にX氏がいるとして、最大値を求める
	int ans = 0,tmp_num;

	for(int i = 0; i < CANDIDATE.size(); i++){

		tmp_num = 0;

		//X氏とその人の間に、ポリゴンがない有権者の数を数える
		for(int k = 0; k < num_human; k++){

			bool FLG = true;

			Line tmp_line;
			tmp_line.p[0] = HUMAN[k];
			tmp_line.p[1] = CANDIDATE[i]; //★伸ばさない★

			for(int a = 0; a < num_polygon; a++){
				for(int b = 0; b < POLYGON[a].size(); b++){

					Line adj_line;

					adj_line.p[0] = POLYGON[a][b];
					adj_line.p[1] = POLYGON[a][(b+1)%POLYGON[a].size()];

					if(!is_Cross(tmp_line,adj_line))continue;

					Point cross_point = calc_Cross_Point(tmp_line.p[0],tmp_line.p[1],adj_line.p[0],adj_line.p[1]);

					if(cross_point == adj_line.p[0] || cross_point == adj_line.p[1]){

						//Do nothing
					}else{

						if(cross_point == CANDIDATE[i])continue;

						FLG = false;
						break;
					}

				}
				if(!FLG)break;
			}

			if(FLG){
				tmp_num++;
			}
		}

		ans = max(ans,tmp_num);
	}

	printf("%d\n",ans);

	return 0;
}



Measured memory_bytes: 3364