#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cmath>
#include <cassert>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
#include <iomanip>
#include <fstream>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)(n);++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
#define chmax(a,b) (a<b?(a=b,1):0)
#define chmin(a,b) (a>b?(a=b,1):0)
#define valid(y,x,h,w) (0<=y&&y<h&&0<=x&&x<w)
const int INF = 1<<29;
const double EPS = 1e-8;
const double PI = acos(-1);
typedef long long ll;
typedef pair<int,int> pii;

typedef complex<double> P;
P pIN() { double x,y; cin >> x >> y; return P(x,y); }
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
double dot(const P& a, const P& b) {
  return real(conj(a)*b);
}
int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > EPS)   return +1;       // counter clockwise
  if (cross(b, c) < -EPS)   return -1;       // clockwise
  if (dot(b, c) < -EPS)     return +2;       // c--a--b on line
  if (EPS < norm(b) && norm(b) < norm(c)-EPS) return -2; // a--b--c on line
  return 0;
}
struct L : public vector<P> {
  L(const P &a, const P &b) {
    push_back(a); push_back(b);
  }
  L() { resize(2); }
};
ostream &operator<<(ostream &os, const L &a) {
  os << a[0] << " -> " << a[1];
  return os;
}
typedef vector<P> G;

typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};

bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}

typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

// テ」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツ?」ツ?凝」ツつ嘉」ツ?ソテ」ツ?淌」ツδ凖」ツつッテ」ツδ暗」ツδォテッツスツづ」ツ?ョティツァツ津・ツコツヲテ」ツ?ョ[0,2pi)
double angle(const P &a, const P &b) {
  double ret = arg(b)-arg(a);
  return (ret>=0) ? ret : ret + 2*PI;
}
// テ」ツδ凖」ツつッテ」ツδ暗」ツδォaテ」ツ?ィテ」ツδ凖」ツつッテ」ツδ暗」ツδォbテ」ツ?ョテゥツ鳴禿」ツ?ョティツァツ津・ツコツヲ
double angle2(const P &a, const P &b) {
  return min(angle(a,b), angle(b,a));
}
double area2(const G& g) {
  double A = 0;
  for (int i = 0; i < g.size(); ++i) {
    A += cross(g[i], g[(i+1)%g.size()]);
  }
  return A;
}
double area(const G&g) {
  return abs(area2(g)/2);
}

G getHolesSub(const Graph &g, const vector<P> &ps, int a, int b, map<pii,bool> &visited) {
  G res;
  int pre = a;
  int cur = b;
  res.push_back(ps[a]);
  while(cur != a) {
    visited[pii(pre,cur)] = 1;
    res.push_back(ps[cur]);
    P vec = ps[pre]-ps[cur];
    double minang = -1;
    int dst = -1;
    FOR(it, g[cur]) {
      double tang = angle(vec, ps[it->dst]-ps[cur]);
      if (chmax(minang, tang)) {
        dst = it->dst;
      }
    }
    if (dst == -1) return G();
    pre = cur;
    cur = dst;
  }
  visited[pii(pre,cur)] = 1;
  if (area2(res) > EPS) return res;
  return G();
}

vector<G> getHoles(const Graph &g, const vector<P> &ps) {
  map<pii, bool> visited;
  vector<G> ret;
  REP(i,g.size()) {
    FOR(it, g[i]) {
      if (visited.count(pii(it->src,it->dst))) continue;
      G t = getHolesSub(g, ps, it->src, it->dst, visited);
      if (t.size()) ret.push_back(t);
    }
  }
  return ret;
}

L line(const G &g, int i) {
  return L(g[i],g[(i+1)%g.size()]);
}

bool eq(const P &a, const P &b) {
  return abs(a-b) < EPS;
}

vector<Weight> dijkstra2(const Graph &g, int s) {
  vector<Weight> dist(g.size(), INF);
  dist[s] = 0;
  priority_queue<Edge> Q; // "e < f" <=> "e.weight > f.weight"
  for (Q.push(Edge(-2, s, 0)); !Q.empty(); ) {
    Edge e = Q.top(); Q.pop();
    if (dist[e.dst] < e.weight) continue;
    FOR(f,g[e.dst]) {
      if (dist[f->dst] > e.weight+f->weight) {
        dist[f->dst] = e.weight+f->weight;
        Q.push(Edge(f->src, f->dst, e.weight+f->weight));
      }
    }
  }
  return dist;
}

int main() {
  int n,m;
  while(cin >> n >> m, n || m) {
    vector<P> ps(n);
    REP(i,n) ps[i] = pIN();
    Graph g(n);
    REP(i,m) {
      int a, b;
      cin >> a >> b;
      a--;b--;
      g[a].push_back(Edge(a,b,1));
      g[b].push_back(Edge(b,a,1));
    }
    vector<G> gs = getHoles(g,ps);
    int N = gs.size();
    Graph g2(N+1);
    REP(i,N) {
      REP(j,gs[i].size()) {
        L l = line(gs[i],j);
        bool f = 0;
        REP(i2,N) {
          if (i2 == i) continue;
          REP(j2,gs[i2].size()) {
            L l2 = line(gs[i2], j2);
            if (eq(l[0],l2[0]) && eq(l[1],l2[1]) ||
                eq(l[0],l2[1]) && eq(l[1],l2[0])) {
              f = 1;
              g2[i].push_back(Edge(i,i2,1));
            }
          }
        }
        if (!f) {
          g2[i].push_back(Edge(i,N,1));
          g2[N].push_back(Edge(N,i,1));
        }
      }
    }
    // REP(i,N+1) {
    //   cout << i << " : ";
    //   FOR(it, g2[i]) {
    //     cout << it->dst << " ";
    //   }
    //   cout << endl;
    // }
    vector<int> weight = dijkstra2(g2,N);
    cout << *max_element(ALL(weight)) << endl;
  }
}

Measured memory_bytes: 1356