//
// [not yet accepted]
//
#include <iostream>
#include <vector>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <map>
#include <queue>
#include <set>
#include <functional>
#include <ctime>
#include <numeric>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(x,a) { auto y=(x); if (sign(y-a)) { cout << "line " << __LINE__  << #x << " = " << y << " != " << a << endl; exit(-1); } }

const double EPS = 1e-8;
int sign(double x) {
  if (x < -EPS) return -1;
  if (x > +EPS) return +1;
  return 0;
}
struct point {
  typedef double T;
  T x, y; 
  point &operator+=(point p) { x += p.x; y += p.y; return *this; }
  point &operator-=(point p) { x -= p.x; y -= p.y; return *this; }
  point &operator*=(T a)     { x *= a;   y *= a;   return *this; }
  point &operator/=(T a)     { return *this *= (1.0/a); }
  point operator-() const    { return {-x, -y}; }
  bool operator<(point p) const { 
    int s = sign(x - p.x);
    return s ? s < 0 : sign(y - p.y) < 0;
  }
};
bool operator==(point p, point q) { return !(p < q) && !(q < p); }
point operator+(point p, point q) { return p += q; }
point operator-(point p, point q) { return p -= q; }
point operator*(point::T a, point p) { return p *= a; }
point operator*(point p, point::T a) { return p *= a; }
point operator/(point p, point::T a) { return p /= a; }
point::T dot(point p, point q) { return p.x*q.x+p.y*q.y; }
point::T cross(point p, point q) { return p.x*q.y-p.y*q.x; } // left turn > 0
point::T norm2(point p) { return dot(p,p); }
point orth(point p) { return {-p.y, p.x}; }
point::T norm(point p) { return sqrt(dot(p,p)); }
point::T arg(point p) { return atan2(p.y, p.x); }

struct line { point p, q; };
bool operator==(line l, line m) {
  return !sign(cross(l.p-l.q,m.p-m.q)) && !sign(cross(l.p-l.q,m.p-l.p));
}

struct segment { point p, q; };
bool operator==(segment l, line m) {
  return (l.p==m.p && l.q==m.q) || (l.p==m.q && l.q==m.p); // do not consider the direction
}
struct circle { point p; point::T r; };
bool operator==(circle c, circle d) { return c.p == d.p && !sign(c.r - d.r); }

typedef vector<point> polygon;

struct polar_angle {
  const point o;
  const int s; // +1 for ccw, -1 for cw
  polar_angle(point p = {0,0}, int s = +1) : o(p), s(s) { }
  int quad(point p) const {
    for (int i = 1; i <= 4; ++i, swap(p.x = -p.x, p.y))
      if (p.x > 0 && p.y >= 0) return i;
    return 0;
  }
  bool operator()(point p, point q) const {
    p = p - o; q = q - o;
    if (quad(p) != quad(q)) return s*quad(p) < s*quad(q);
    if (cross(p, q)) return s*cross(p, q) > 0;
    return norm2(p) < norm2(q); // closer first
  }
};

vector<point> intersect(segment s, segment t) {
  auto a = cross(s.q - s.p, t.q - t.p);
  auto b = cross(t.p - s.p, t.q - t.p); 
  auto c = cross(s.q - s.p, s.p - t.p);
  if (a < 0) { a = -a; b = -b; c = -c; }
  if (sign(b) < 0 || sign(a-b) < 0 ||
      sign(c) < 0 || sign(a-c) < 0) return {};      // disjoint
  if (sign(a) != 0) return {s.p + b/a*(s.q - s.p)}; // properly crossing
  vector<point> ps;                                 // same line
  auto insert_if_possible = [&](point p) {
    for (auto q: ps) if (sign(dot(p-q, p-q)) == 0) return;
    ps.push_back(p);
  };
  if (sign(dot(s.p-t.p, s.q-t.p)) <= 0) insert_if_possible(t.p);
  if (sign(dot(s.p-t.q, s.q-t.q)) <= 0) insert_if_possible(t.q);
  if (sign(dot(t.p-s.p, t.q-s.p)) <= 0) insert_if_possible(s.p);
  if (sign(dot(t.p-s.q, t.q-s.q)) <= 0) insert_if_possible(s.q);
  return ps;
}

struct arrangement {
  struct edge {
    int src, dst;
    point::T weight;
    size_t id, rev;
  };
  int n;
  vector<point> ps; // ps[id[p]] = p, id[ps[k]] = k
  map<point,int> id; 
  vector<vector<edge>> adj;

  arrangement(vector<segment> ss) : n(0) {
    vector<vector<pair<point::T, int>>> group(ss.size());
    auto append = [&](int i, point p) {
      if (!id.count(p)) { id[p] = n++; ps.push_back(p); }
      group[i].push_back({norm(ss[i].p - p), id[p]});
    };
    for (int i = 0; i < ss.size(); ++i) {
      append(i, ss[i].p); append(i, ss[i].q);
      for (int j = 0; j < i; ++j) {
        for (point p: intersect(ss[i], ss[j])) {
          append(i, p); append(j, p);
        }
      }
    }
    adj.resize(n);
    for (auto &vs: group) {
      sort(all(vs));
      for (int i = 0; i+1 < vs.size(); ++i) {
        auto u = vs[i].snd, v = vs[i+1].snd;
        if (u == v) continue;
        auto len = vs[i+1].fst - vs[i].fst;
        adj[u].push_back({u, v, len});
        adj[v].push_back({v, u, len});
      }
    }
    // remove duplicates and orient edges
    vector<unordered_map<int, int>> idx(n);
    for (int u = 0; u < n; ++u) {
      auto eq = [&](edge e, edge f) { return e.dst == f.dst; };
      auto lt = [&](edge e, edge f) { return e.dst <  f.dst; };
      sort(all(adj[u]), lt);
      adj[u].erase(unique(all(adj[u]), eq), adj[u].end());
      sort(all(adj[u]), [&](edge e, edge f) {
        return arg(ps[e.dst] - ps[e.src]) > arg(ps[f.dst] - ps[f.src]);
      });
      for (int i = 0; i < adj[u].size(); ++i) {
        adj[u][i].id = i;
        int v = adj[u][i].dst;
        idx[u][v] = i;
        if (idx[v].count(u)) {
          int j = idx[v][u];
          adj[u][i].rev = j;
          adj[v][j].rev = i;
        }
      }
    }
  }
  edge twin(edge e) const { return adj[e.dst][e.rev]; }
  edge next(edge e) const {
    int j = adj[e.dst][e.rev].id + 1;
    if (j >= adj[e.dst].size()) j = 0;
    return adj[e.dst][j];
  }
  edge outer() const {
    int s = 0;
    for (int i = 1; i < n; ++i) if (ps[i] < ps[s]) s = i;
    for (int i = 0; i < adj[s].size(); ++i) {
      edge e1 = adj[s][i], e2 = adj[s][(i+1)%adj[s].size()];
      if (cross(ps[e1.dst]-ps[s], ps[e2.dst]-ps[s]) <= 0) return e1;
    }
  }
};
istream &operator>>(istream &is, point &p) { is>>p.x>>p.y;return is; }
ostream &operator<<(ostream &os, const point &p) { os<<"("<<p.x<<","<<p.y<<")"; return os; }


struct visualizer {
  double minx, maxx, miny, maxy, scale; 
  ofstream ofs;
  visualizer(string s = "data.js") : ofs(s) { 
    minx = miny =  1.0/0.0;
    maxx = maxy = -1.0/0.0;
  }
  void update(point p) {
    minx = min(minx, p.x); miny = min(miny, p.y);
    maxx = max(maxx, p.x); maxy = max(maxy, p.y);
    scale = 480/(max({maxx-minx, maxy-miny,1.0}));
  }
  double X(point p) { return scale * (p.x-minx) + 10; }
  double Y(point p) { return 490 - scale * (p.y-miny); }
  vector<point> ps;
  vector<segment> ss;
  visualizer &operator<<(point p) { ps.push_back(p); update(p); return *this; }
  visualizer &operator<<(segment s) { ss.push_back(s); update(s.p); update(s.q); return *this; }
  ~visualizer() {
    for (point p: ps) 
      ofs << "circle(" << X(p) << "," << Y(p) << ",3.0)" << endl;
    for (segment s: ss) 
      ofs << "line(" << X(s.p) << "," << Y(s.p) << "," 
                     << X(s.q) << "," << Y(s.q) << ")" << endl;
  }
};


int main() {
  for (int c, w; ~scanf("%d %d", &c, &w) && c; ) {
    vector<point> ps(c);
    for (int i = 0; i < c; ++i) {
      scanf("%lf %lf", &ps[i].x, &ps[i].y);
    }
    vector<segment> ss;
    for (int i = 0; i < w; ++i) {
      int u, v; scanf("%d %d", &u, &v);
      ss.push_back({ps[u-1], ps[v-1]});
    }
    arrangement arr(ss);
    /*
    visualizer vis;
    for (int i = 0; i < arr.n; ++i) {
      cerr << i << ": " << arr.ps[i] << endl;
      vis << arr.ps[i];
      for (auto e: arr.adj[i]) {
        vis << segment({arr.ps[e.src], arr.ps[e.dst]});
      }
    }
    */

    typedef arrangement::edge edge;
    edge e = arr.outer(); // outer-face edge

    vector<unordered_map<int,int>> step(arr.n);
    queue<edge> que;
    auto proceed = [&](edge s, int value) {
      if (step[s.src].count(s.dst)) return;
      //cerr << "proceed edge " << arr.ps[e.src] << arr.ps[e.dst] << endl;
      edge e = s;
      do {
        //cerr << "  mark " << arr.ps[e.src] << arr.ps[e.dst] << endl;
        step[e.src][e.dst] = value;
        que.push(arr.twin(e));
        e = arr.next(e);
      } while (e.src != s.src || e.dst != s.dst);
    };
    proceed(e, 0);
    int ans = 0;
    while (!que.empty()) {
      edge e = que.front(); que.pop();
      ans = step[e.dst][e.src];
      proceed(e, ans + 1);
    }
    printf("%d\n", ans);
  }
}

Measured memory_bytes: 3596