#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n==0) ? 1 : 10*TEN(n-1); }
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;

using D = double;
using P = complex<D>;

const D PI = acos(D(-1)), EPS = 1e-10;

int sgn(D a) {
    if (abs(a) <= EPS) return 0;
    return (a < 0) ? -1 : 1;
}
bool near(P a, P b) { return !sgn(abs(a-b)); }
D mabs(P p) { return abs(p.real()) + abs(p.imag()); }

bool lessP(P l, P r) {
    if (sgn(r.real()-l.real())) return l.real() < r.real();
    if (sgn(r.imag()-l.imag())) return l.imag() < r.imag();
    return false;
}

D cross(P a, P b) { return a.real()*b.imag() - a.imag()*b.real(); }
D dot(P a, P b) { return a.real()*b.real() + a.imag()*b.imag(); }

// -2, -1, 0, 1, 2 : front, clock, on, cclock, back
int ccw(P b, P c) {
    int s = sgn(cross(b, c) / mabs(b));
    if (s) return s;
    if (!sgn(mabs(c)) || !sgn(mabs(c-b))) return 0;
    if (dot(b, c) < 0) return 2;
    if (dot(-b, c-b) < 0) return -2;
}
int ccw(P a, P b, P c) { return ccw(b-a, c-a); }

struct L {
    P x, y;
    L() {}
    L(P x, P y) :x(x), y(y) {}
    P vec() const { return y-x; }
};
D abs(const L &l) { return abs(l.vec()); }
D arg(const L &l) { return arg(l.vec()); }

D distLP(const L &l, const P &p) {
    return abs(cross(l.vec(), p-l.x)/abs(l.vec()));
}
D distSP(const L &s, const P &p) {
    P s2 = s.vec()*P(0, 1);
    if (ccw(s.x, s.x+s2, p) == 1) return abs(s.x-p);
    if (ccw(s.y, s.y+s2, p) == -1) return abs(s.y-p);
    return min(min(abs(s.x-p), abs(s.y-p)), distLP(s, p));
}


int crossLL(const L &l, const L &m, P &r) {
    L mm = L(m.x - l.x, m.y - l.x);
    mm.x *= polar<D>(1, -arg(l));
    mm.y *= polar<D>(1, -arg(l));
    if (sgn(mm.vec().imag()) == 0) {
        r = l.x;
        if (sgn(mm.x.imag()) == 0) return -1;
        return 0;
    }
    r = mm.x - mm.vec() * (mm.x.imag() / mm.vec().imag());
    r *= polar<D>(1, arg(l));
    r += l.x;
    return 1;
}
int crossSS(const L &l, const L &m, P &r) {
    int u = crossLL(l, m, r);
    if (u == 0) return 0;
    if (u == -1) {
        int x = ccw(l.x, l.y, m.x);
        int y = ccw(l.x, l.y, m.y);
        if (x == 0) {
            r = m.x;
            return -1;
        }
        if (y == 0) {
            r = m.y;
            return -1;
        }
        if (x == y) return 0;
        r = l.x;
        return -1;
    }
    if (ccw(l.x, l.y, r) == 0 && ccw(m.x, m.y, r) == 0) return 1;
    return 0;
}

using Pol = V<P>;

P cu(const Pol &p, int i) {
    int s = p.size();
    return p[(i%s+s)%s];
};
//0:P is out 1:P is on line 2:P is in
int contains(const Pol &pol, P p) {
    int in = -1;
    for (int i = 0; i < int(pol.size()); i++) {
        P a=cu(pol,i)-p, b=cu(pol,i+1)-p;
        if (ccw(a, b, P(0, 0)) == 0) return 1;
        if (imag(a) > imag(b)) swap(a, b);
        if (imag(a) <= 0 && 0 < imag(b)) {
            if (cross(a, b) < 0) in *= -1;
        }
    }
    return in+1;
}

D area_naive(const Pol &p) {
    D u = 0;
    for (int i = 0; i < (int)p.size(); i++) {
        u += cross(cu(p, i), cu(p, i+1));
    }
    return u/2;
}

/*
 -1 -> clock
 0 -> non polygon
 1 -> counter clock
 */
int iscclock(const Pol &p) {
    return sgn(area_naive(p));
}

//0:P is out 1:P is on line 2:P is in
int contains(const Pol &pol, const L &l) {
    vector<P> v;
    v.push_back(l.x); v.push_back(l.y);
    for (int i = 0; i < (int)pol.size(); i++) {
        P a = cu(pol, i), b = cu(pol, i+1);
        P p;
        if (crossSS(L(a, b), l, p)) {
            v.push_back(p);
        }
    }

    sort(v.begin(), v.end(), [&](const P &x, const P &y){
        return abs(l.x-x) < abs(l.x-y);
    });

    int sz = (int)v.size();
    for (int i = 0; i < sz-1; i++) {
        v.push_back((v[i]+v[i+1])/D(2));
    }
    bool f = false;
    for (P p: v) {
        int u = contains(pol, p); 
        if (!u) return 0;
        if (u == 2) f = true;
    }
    if (f) return 2;
    return 1;
}


/*
 双対グラフを作成
 pol, rgの要素は2*n-4個確保しておくこと
 gはめちゃくちゃに破壊される
 もし連結でないグラフ、しかも内包があるグラフに行うとrgは0が複数混入する
 0は、その連結成分だけに注目したときの外側の意味。本当に外側か判定したいなら
 contains等を使用すること
 */
int dualGraph(P p[], vector<int> g[], int n,
    Pol pol[], vector<int> rg[]) {
    map<pair<int, int>, int> mp;
    for (int i = 0; i < n; i++) {
        sort(g[i].begin(), g[i].end());
        assert(unique(g[i].begin(), g[i].end()) == g[i].end());
        sort(g[i].begin(), g[i].end(), [&](int l, int r){
            return arg(p[l]-p[i]) > arg(p[r]-p[i]);
        });
        for (int j = 0; j < (int)g[i].size(); j++) {
            mp[make_pair(i, g[i][j])] = j;
        }
    }

    vector<vector<int>> idx(n), rev(n);
    for (int i = 0; i < n; i++) {
        idx[i] = vector<int>(g[i].size(), -1);
        rev[i].resize(g[i].size());
        for (int j = 0; j < (int)g[i].size(); j++) {
            rev[i][j] = mp[make_pair(g[i][j], i)];
        }
    }

    int idc = 1;
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < (int)g[i].size(); j++) {
            if (idx[i][j] != -1) continue;
            Pol po;
            int ii = i, jj = j;
            while (idx[ii][jj] != -2) {
                po.push_back(p[ii]);
                idx[ii][jj] = -2;
                int ni = g[ii][jj];
                int nj = (rev[ii][jj]+1) % g[ni].size();
                ii = ni; jj = nj;
            }
            int id;
            if (iscclock(po) != 1) {
                id = 0;
            } else {
                id = idc;
                pol[idc] = po;
                idc++;
            }
            while (idx[ii][jj] == -2) {
                idx[ii][jj] = id;
                int ni = g[ii][jj];
                int nj = (rev[ii][jj]+1) % g[ni].size();
                ii = ni; jj = nj;
            }
        }
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < (int)g[i].size(); j++) {
            if (idx[i][j] != 0) continue;
            int id = 0;
            for (int k = 1; k < idc; k++) {
                if (contains(pol[k], p[i]) == 2) {
                    id = k;
                }
            }
            if (id == 0) continue;
            int ii = i, jj = j;
            while (idx[ii][jj] == 0) {
                idx[ii][jj] = id;
                int ni = g[ii][jj];
                int nj = (rev[ii][jj]+1) % g[ni].size();
                ii = ni; jj = nj;
            }            
        }
    }

    for (int i = 0; i < idc; i++) {
        rg[i].clear();
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < (int)g[i].size(); j++) {
            if (idx[i][j] < 0) continue;
            rg[idx[i][j]].push_back(idx[g[i][j]][rev[i][j]]);
        }
    }

    for (int i = 0; i < n; i++) {
        sort(rg[i].begin(), rg[i].end());
        rg[i].erase(unique(rg[i].begin(), rg[i].end()), rg[i].end());
    }

    return idc;
}






const int MN = 110;
 
 
P p[MN];
vector<int> g[MN];
 
Pol pol[2*MN];
vector<int> rg[2*MN];
 
int dist[2*MN][2*MN];
 
bool solve() {
    int c, w;
    cin >> c >> w;
    if (!c) return false;
 
    for (int i = 0; i < c; i++) {
        D x, y;
        cin >> x >> y;
        p[i] = P(x, y);
        g[i].clear();
    }
 
    for (int i = 0; i < w; i++) {
        int s, t;
        cin >> s >> t; s--; t--;
        g[s].push_back(t);
        g[t].push_back(s);
    }
 
    dualGraph(p, g, c, pol, rg);
    int ma = 0;
    bool used[2*MN] = {};
    queue<pair<int, int>> q;
    q.push(make_pair(0, 0));
    while (q.size()) {
        int t, di;
        tie(t, di) = q.front(); q.pop();
        if (used[t]) continue;
        used[t] = true;
        ma = max(ma, di);
        for (int d: rg[t]) {
            if (used[d]) continue;
            q.push(make_pair(d, di+1));
        }
    }
    cout << ma << endl;
    return true;
}
 
 
int main() {
    while (solve()) {}
    return 0;
}



Measured memory_bytes: 3608