#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;



#define SIZE 105

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 Edge{
	Edge(int arg_to,double arg_theta){
		to = arg_to;
		theta = arg_theta;
	}
	bool operator<(const struct Edge &arg) const{

		return theta < arg.theta;
	}

	int to;
	double theta;
};

struct Info{
	Info(int arg_area_id,int arg_sum_dist){
		area_id = arg_area_id;
		sum_dist = arg_sum_dist;
	}
	bool operator<(const struct Info &arg) const{

		return sum_dist > arg.sum_dist; //総距離の降順(PQ)
	}

	int area_id,sum_dist;
};

typedef Point Vector;

struct Line{
	Line(){

	}
	Line(Point a,Point b){
		p[0] = a;
		p[1] = b;
	}
	Point p[2];
};


int num_pillar,num_wall;
Point point[SIZE];
vector<Edge> G[SIZE];
int min_dist[100*33*49];


vector<int> get_area(int first_from,int first_to){

	vector<int> ret;

	int from = first_from;
	int to = first_to;

	do{

		ret.push_back(from);
		int next = to;

		for(int k = 0; k < G[next].size(); k++){
			if(G[next][k].to == from){
				if(k != 0){

					to = G[next][k-1].to;

				}else{

					to = G[next][G[to].size()-1].to;
				}

				break;
			}
		}
		from = next;

	}while(from != first_from || to != first_to);

	return ret;
}


vector<int> pol_sort(vector<int> polygon){

	int min_index = BIG_NUM,loc;

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

		if(min_index > polygon[i]){
			min_index = polygon[i];
			loc = i;
		}
	}

	//min_indexが先頭になるようにする
	for(int i = 0; i < loc; i++){

		polygon.push_back(polygon[0]);
		polygon.erase(polygon.begin());
	}

	return polygon;
}

double get_theta(Vector A){

	double ret = atan2(A.y,A.x);

	if(ret < 0){

		ret += 2*M_PI;
	}
	return ret;
}


double norm(Vector a){
	return a.x*a.x+a.y*a.y;
}

double abs(Vector a){
	return sqrt(norm(a));
}

double cross(Vector a,Vector b){
    return a.x*b.y-a.y*b.x;
}

double dot(Vector a,Vector b){
    return a.x*b.x + a.y*b.y;
}

void func(){

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

		G[i].clear();
	}

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

		scanf("%lf %lf",&point[i].x,&point[i].y);
	}

	int from,to;

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

		scanf("%d %d",&from,&to);

		from--;
		to--;

		G[from].push_back(Edge(to,get_theta(point[from]-point[to])));
		G[to].push_back(Edge(from,get_theta(point[to]-point[from])));
	}

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

		sort(G[i].begin(),G[i].end());
	}

	vector<vector<int>> first_POLYGON;

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

		for(int k = 0; k < G[i].size(); k++){

			vector<int> polygon = pol_sort(get_area(i,G[i][k].to));

			first_POLYGON.push_back(polygon);
		}
	}

	sort(first_POLYGON.begin(),first_POLYGON.end());
	first_POLYGON.erase(unique(first_POLYGON.begin(),first_POLYGON.end()),first_POLYGON.end());

	vector<vector<int>> POLYGON;
	vector<int> A,B;

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

		bool FLG = true;
		A = first_POLYGON[i];
		sort(A.begin(),A.end());

		for(int k = 0; k < i; k++){
			B = first_POLYGON[k];
			sort(B.begin(),B.end());

			if(A == B){

				FLG = false;
				break;
			}

		}
		if(FLG){
			POLYGON.push_back(first_POLYGON[i]);
		}
	}

	if(POLYGON.size() == 1){

		printf("1\n");
		return;
	}

	vector<int> dist_1;

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

		double tmp = 0;

		for(int k = 0; k < POLYGON[i].size(); k++){

			tmp += cross(point[POLYGON[i][k]],point[POLYGON[i][(k+1)%POLYGON[i].size()]]);
		}
		if(tmp < EPS){
			dist_1.push_back(i);
		}
	}

	int num_area = POLYGON.size();
	vector<int> final_G[num_area];


	for(int i = 0; i < num_area-1; i++){ //領域

		for(int a = 0; a < POLYGON[i].size(); a++){ //辺の走査

			Line tmp_line = Line(point[POLYGON[i][a]],point[POLYGON[i][(a+1)%POLYGON[i].size()]]);

			bool FLG = false;

			for(int k = i+1; k < num_area; k++){ //隣接領域
				if(k == i)continue;

				for(int b = 0; b < POLYGON[k].size(); b++){ //隣接領域の辺
					Line tmp_line2 = Line(point[POLYGON[k][b]],point[POLYGON[k][(b+1)%POLYGON[k].size()]]);

					if((tmp_line.p[0] == tmp_line2.p[0] && tmp_line.p[1] == tmp_line2.p[1]) ||
							(tmp_line.p[0] == tmp_line2.p[1] && tmp_line.p[1] == tmp_line2.p[0])){

						FLG = true;
						final_G[i].push_back(k);
						final_G[k].push_back(i);

						break;
					}
				}
				if(FLG)break;
			}
		}
	}

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

		min_dist[i] = BIG_NUM;
	}

	priority_queue<Info> Q;

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

		min_dist[dist_1[i]] = 1;
		Q.push(Info(dist_1[i],1));
	}

	while(!Q.empty()){

		if(Q.top().sum_dist > min_dist[Q.top().area_id]){

			Q.pop();

		}else{

			for(int i = 0; i < final_G[Q.top().area_id].size(); i++){

				int next_area = final_G[Q.top().area_id][i];
				int next_dist = Q.top().sum_dist+1;

				if(min_dist[next_area] > next_dist){
					min_dist[next_area] = next_dist;
					Q.push(Info(next_area,next_dist));
				}
			}
			Q.pop();
		}
	}

	int ans = 0;

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

		ans = max(ans,min_dist[i]);
	}

	printf("%d\n",ans-1);
}

int main(){

	while(true){

		scanf("%d %d",&num_pillar,&num_wall);
		if(num_pillar == 0 && num_wall == 0)break;

		func();
	}

	return 0;
}



Measured memory_bytes: 3616