Problem:
ねこまっしぐら２
あるところに大きな古いお屋敷があり、１匹のねこが住み着いていました。図のように、お屋敷は上空から見ると凸多角形になっており、まっすぐな壁で囲まれたいくつかの部屋で造られています。１枚の壁はその両端にある柱によって支えられています。お屋敷はとても古いため、どの壁にもねこが通ることができるくらいの穴が１つ空いています。ねこは壁の穴を通ってお屋敷の部屋と部屋または部屋と外を行き来することができます。
お屋敷のご主人は、ねこに餌をあげるために、口笛を吹いてねこをお屋敷の外へ呼び出します。ねこはとても賢く、ご主人が口笛を吹くと、「最良の選択」でお屋敷の外へ抜け出します。つまり、最も少ない回数だけ穴を通って外へ出ます。
ねこはとても気まぐれで、どの部屋にいるか分かりません。そのため、ねこがお屋敷の外へ出るのにかかる時間は日によって異なり、ご主人はどれだけ待てばよいかわからず困っていました。ある時ご主人は、ねこが穴を通り抜けるときに、とても時間がかかっていることに気が付きました。ということは、ねこが外に出るのにかかる時間は穴を通る回数によって決まることになります。ご主人は、ねこが「最良の選択」をした場合の穴を通る回数の最大値が分かれば、ねこがどの部屋にいたとしても、最大どれだけ待てばよいか分かるのではないかと考えました。ご主人はお屋敷の間取りを知っていますが、お屋敷はとても大きく、自分では計算することができません...。
お屋敷の間取りを読み込み、ねこが「最良の選択」をした場合、外に出るまでに通る穴の数の最大値を
出力するプログラムを作成して下さい。
入力
入力は複数のデータセットからなる。入力の終わりはゼロ２つの行で示される。各データセットは以下の形式で与えられる。
C W
x
1
y
1
x
2
y
2
:
x
C
y
C
s
1
t
1
s
2
t
2
:
s
W
t
W
各行で与えられる数値は１つの空白で区切られている。
１行目に柱の数 C (3 ≤ C ≤ 100) と壁の数 W (3 ≤ W ≤ 300) が与えられる。続く C 行に柱の座標が与えられる。x
i
(-1000 ≤ x
i
≤ 1000) は i 番目の柱の x 座標、y
i
(-1000 ≤ y
i
≤ 1000) は i 番目の柱の y 座標をそれぞれ示す整数である。柱にはそれぞれ 1 から C までの番号が割り当てられている。 続く W 行に壁の情報が与えられる。
s
i
(1 ≤ s
i
≤ C)、t
i
(1 ≤ t
i
≤ C) は壁の両端を支える柱の番号を示す。
入力は以下の条件を満たすと考えてよい。
異なる柱が同じ位置を占めることはない。
異なる壁が重なったり、柱以外で交差することはない。
１つの柱は２つ以上の壁を支えている。
壁の長さは 0 より大きい。
柱は壁の両端だけにある。つまり、柱が壁の途中にあることはない。
壁は異なる２つの部屋、あるいは部屋と外とを仕切る。
任意の異なる２つの柱を選んだとき、互いの柱には壁をたどって到達できる。
データセットの数は 50 を超えない。
出力
データセットごとに、ねこが「最良の選択」をした場合、外に出るまでに通る穴の数の最大値を１行に出力する。
入力例
4 4
0 0
1 0
1 1
0 1
1 2
1 4
2 3
3 4
12 22
2 0
4 0
8 0
4 2
6 2
8 2
2 4
4 4
6 4
0 6
8 6
0 8
1 2
2 3
1 4
1 7
1 10
2 4
2 5
3 5
3 6
4 5
4 8
5 6
5 9
6 9
6 11
7 10
7 8
8 9
9 11
10 11
10 12
11 12
0 0
出力例
1
3
２つ目のデータセットが、冒頭の図に示したお屋敷の間取りに対応する。図のように、薄く色が塗られた部屋にねこがいるときは、「最良の選択」で外に出るまでに通り抜ける穴の数は３つである。それ以外の部屋にねこがいるときは、２つ以下で外に出られる。したがって、ねこが「最良の選択」をしたとき、外に出るまでに通り抜ける穴の数の最大値は 3 になる。

Submitted solutions:

code_snippet: #include <bits/stdc++.h>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

using ll = long long;
using ld = long double;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "Yes"; }
  string_type do_falsename() const { return "No"; }
};

using ld = long double;
using P = complex<ld>;
using VP = vector<P>;
const ld eps = 1e-8, pi = acos(-1.0);

P input() { ld x, y; cin >> x >> y; return P(x, y); }

ld dot (P a, P b) { return real(conj(a) * b); }
ld cross (P a, P b) { return imag(conj(a) * b); }

struct L{ P a, b; };
struct C { P p; ld r; };

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) < 0) return 2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line
  return 0;                          // a--c--b on line
}

int is_clockwise(const vector<P> &ps) {
  int n = ps.size();
  ld sum = 0;
  REP(i,n) {
    P v1 = ps[(i+1)%n] - ps[i];
    P v2 = ps[(i+2)%n] - ps[(i+1)%n];
    sum += arg(v2 / v1);
  }
  return sum > 0;
}

struct Edge{ int src, dest; };

using Edges = vector<Edge>;
using Graph = vector<Edges>;

vector<vector<int>> polygon;
vector<int> seg2p[1024][1024];
 
Graph dual_graph(const vector<L> &s, const VP &p) {
  int N = p.size();
  polygon.clear();
  REP(i,1024) REP(j,1024) seg2p[i][j].clear();
  vector<vector<tuple<ld,int,bool>>> tup(N);
  REP(i,s.size()) {
    int a = -1, b = -1;
    REP(j,N) if (abs(s[i].a - p[j]) < eps) a = j;
    REP(j,N) if (abs(s[i].b - p[j]) < eps) b = j;
    assert(a >= 0 && b >= 0);
    tup[a].emplace_back(arg(s[i].b - s[i].a), b, false);
    tup[b].emplace_back(arg(s[i].a - s[i].b), a, false);
  }
  REP(i,N) sort(ALL(tup[i]));
  REP(i,N) {
    REP(j,tup[i].size()) {
      ld angle; int pos = j, src = i, dest; bool flag;
      tie(angle, dest, flag) = tup[i][j];
      if (flag) continue;
      vector<int> ps;
      while (!flag) {
        ps.push_back(src);
        get<2>(tup[src][pos]) = true;
        seg2p[src][dest].push_back(polygon.size());
        seg2p[dest][src].push_back(polygon.size());
        angle += pi + eps;
        if (angle > pi) angle -= 2 * pi;
        auto it = lower_bound(ALL(tup[dest]), make_tuple(angle, 0, false));
        if (it == tup[dest].end()) it = tup[dest].begin();
        src = dest; tie(angle, dest, flag) = *it;
        pos = it - tup[src].begin();
      }
      polygon.push_back(ps);
    }
  }
  Graph g(polygon.size());
  REP(i,N) REP(j,i) {
    if (seg2p[i][j].size() == 2) {
      int src = seg2p[i][j][0], dest = seg2p[i][j][1];
      g[src].push_back((Edge){src, dest});
      g[dest].push_back((Edge){dest, src});
    }
  }
  return g;
}

void bfs(Graph &g, vector<int> &d, int s) {
  d.assign(g.size(), -1);
  d[s] = 0;
  queue<int> que;
  que.push(s);
  while (!que.empty()) {
    int v = que.front();
    que.pop();
    for (auto e: g[v]) {
      if (d[e.dest] == -1) {
        d[e.dest] = d[v] + 1;
        que.push(e.dest);
      }
    }
  }
}

int main() {
  locale loc(locale(), new yes_no);
  cout << boolalpha << setprecision(12) << fixed;
  cout.imbue(loc);

  int C, W;
  while (cin >> C >> W, C) {
    vector<P> points(C);
    vector<L> segments(W);
    REP(i,C) points[i] = input();
    REP(i,W) {
      int s, t;
      cin >> s >> t; --s; --t;
      segments[i] = L({points[s], points[t]});
    }
    Graph g = dual_graph(segments, points);
    int V = g.size();
    int start = 0;
    REP(i,V) {
      vector<P> poly;
      for (int j: polygon[i]) {
        poly.push_back(points[j]);
      }
      if (is_clockwise(poly)) start = i;
    }
    vector<int> d;
    bfs(g, d, start);
    cout << *max_element(ALL(d)) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 28156
final_rank: 15

code_snippet: #include <bits/stdc++.h>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

using ll = long long;
using ld = long double;

template <typename T> T &chmin(T &a, const T &b) { return a = min(a, b); }
template <typename T> T &chmax(T &a, const T &b) { return a = max(a, b); }

struct yes_no : numpunct<char> {
  string_type do_truename()  const { return "Yes"; }
  string_type do_falsename() const { return "No"; }
};

using ld = long double;
using P = complex<ld>;
using VP = vector<P>;
const ld eps = 1e-8, pi = acos(-1.0);

P input() { ld x, y; cin >> x >> y; return P(x, y); }

ld dot (P a, P b) { return real(conj(a) * b); }
ld cross (P a, P b) { return imag(conj(a) * b); }

struct L{ P a, b; };
struct C { P p; ld r; };

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) < 0) return 2;       // c--a--b on line
  if (norm(b) < norm(c)) return -2;  // a--b--c on line
  return 0;                          // a--c--b on line
}

int is_clockwise(const vector<P> &ps) {
  int n = ps.size();
  ld sum = 0;
  REP(i,n) {
    P v1 = ps[(i+1)%n] - ps[i];
    P v2 = ps[(i+2)%n] - ps[(i+1)%n];
    sum += arg(v2 / v1);
  }
  return sum > 0;
}

struct Edge{ int src, dest; };

using Edges = vector<Edge>;
using Graph = vector<Edges>;

vector<vector<int>> polygon;
vector<int> seg2p[1024][1024];
 
Graph dual_graph(const vector<L> &s, const VP &p) {
  int N = p.size();
  polygon.clear();
  REP(i,1024) REP(j,1024) seg2p[i][j].clear();
  vector<vector<tuple<ld,int,bool>>> tup(N);
  REP(i,s.size()) {
    int a = -1, b = -1;
    REP(j,N) if (abs(s[i].a - p[j]) < eps) a = j;
    REP(j,N) if (abs(s[i].b - p[j]) < eps) b = j;
    assert(a >= 0 && b >= 0);
    tup[a].emplace_back(arg(s[i].b - s[i].a), b, false);
    tup[b].emplace_back(arg(s[i].a - s[i].b), a, false);
  }
  REP(i,N) sort(ALL(tup[i]));
  REP(i,N) {
    REP(j,tup[i].size()) {
      ld angle; int pos = j, src = i, dest; bool flag;
      tie(angle, dest, flag) = tup[i][j];
      if (flag) continue;
      vector<int> ps;
      while (!flag) {
        ps.push_back(src);
        get<2>(tup[src][pos]) = true;
        seg2p[src][dest].push_back(polygon.size());
        seg2p[dest][src].push_back(polygon.size());
        angle += pi + eps;
        if (angle > pi) angle -= 2 * pi;
        auto it = lower_bound(ALL(tup[dest]), make_tuple(angle, 0, false));
        if (it == tup[dest].end()) it = tup[dest].begin();
        src = dest; tie(angle, dest, flag) = *it;
        pos = it - tup[src].begin();
      }
      polygon.push_back(ps);
    }
  }
  Graph g(polygon.size());
  REP(i,N) REP(j,i) {
    if (seg2p[i][j].size() == 2) {
      int src = seg2p[i][j][0], dest = seg2p[i][j][1];
      g[src].push_back((Edge){src, dest});
      g[dest].push_back((Edge){dest, src});
    }
  }
  return g;
}

void bfs(Graph &g, vector<int> &d, int s) {
  d.assign(g.size(), -1);
  d[s] = 0;
  queue<int> que;
  que.push(s);
  while (!que.empty()) {
    int v = que.front();
    que.pop();
    for (auto e: g[v]) {
      if (d[e.dest] == -1) {
        d[e.dest] = d[v] + 1;
        que.push(e.dest);
      }
    }
  }
}

int main() {
  locale loc(locale(), new yes_no);
  cout << boolalpha << setprecision(12) << fixed;
  cout.imbue(loc);

  int C, W;
  while (cin >> C >> W, C) {
    vector<P> points(C);
    vector<L> segments(W);
    REP(i,C) points[i] = input();
    REP(i,W) {
      int s, t;
      cin >> s >> t; --s; --t;
      segments[i] = L({points[s], points[t]});
    }
    Graph g = dual_graph(segments, points);
    int V = g.size();
    int start = 0;
    REP(i,V) {
      vector<P> poly;
      for (int j: polygon[i]) {
        poly.push_back(points[j]);
      }
      if (is_clockwise(poly)) start = i;
    }
    vector<int> d;
    bfs(g, d, start);
    cout << *max_element(ALL(d)) << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 90
memory_kb: 28160
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double eps = 0.000001;
int sign(double x){
  if (x > eps){
    return 1;
  } else if (x < -eps){
    return -1;
  } else {
    return 0;
  }
}
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
  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 k){
    return point(x * k, y * k);
  }
  point operator /(double k){
    return point(x / k, y / k);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
double dist(point P, point Q){
  return abs(Q - P);
}
point rotate(point P, double t){
  return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t));
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
bool is_parallel(line L1, line L2){
  return abs(cross(vec(L1), vec(L2))) < eps;
}
bool segment_line_intersect(line L1, line L2){
  return sign(cross(L1.A - L2.A, vec(L2))) * sign(cross(L1.B - L2.A, vec(L2))) <= 0;
}
bool segment_intersect(line L1, line L2){
  return segment_line_intersect(L1, L2) && segment_line_intersect(L2, L1);
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
vector<double> unique_eps(vector<double> A){
  int N = A.size();
  sort(A.begin(), A.end());
  vector<double> A2;
  A2.push_back(A[0]);
  for (int i = 1; i < N; i++){
    if (A[i] - A[i - 1] > eps){
      A2.push_back(A[i]);
    }
  }
  return A2;
}
template <typename T>
struct slab_decomposition{
  function<T(T, T)> f;
  T e;
  vector<pair<line, T>> S;
  vector<double> X;
  int N;
  vector<vector<double>> Y;
  vector<int> P;
  vector<vector<tuple<int, int, T>>> E;
  slab_decomposition(function<T(T, T)> f, T e): f(f), e(e){
  }
  void add_segment(line s, T x){
    S.push_back(make_pair(s, x));
  }
  vector<vector<pair<T, int>>> build(){
    int M = S.size();
    for (int i = 0; i < M; i++){
      if (S[i].first.A.x > S[i].first.B.x){
        swap(S[i].first.A, S[i].first.B);
      }
    }
    for (int i = 0; i < M; i++){
      X.push_back(S[i].first.A.x);
      X.push_back(S[i].first.B.x);
    }
    for (int i = 0; i < M; i++){
      for (int j = i + 1; j < M; j++){
        if (!is_parallel(S[i].first, S[j].first) && segment_intersect(S[i].first, S[j].first)){
          X.push_back(line_intersection(S[i].first, S[j].first).x);
        }
      }
    }
    X = unique_eps(X);
    N = X.size();
    vector<int> L(M), R(M);
    for (int i = 0; i < M; i++){
      L[i] = lower_bound(X.begin(), X.end(), S[i].first.A.x - eps) - X.begin();
      R[i] = lower_bound(X.begin(), X.end(), S[i].first.B.x - eps) - X.begin();
    }
    vector<vector<double>> A(M, vector<double>(N));
    Y.resize(N);
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j <= R[i]; j++){
        A[i][j] = line_intersection(S[i].first, line(point(X[j], 0), point(X[j], 1))).y;
        Y[j].push_back(A[i][j]);
      }
    }
    for (int i = 0; i < N; i++){
      Y[i] = unique_eps(Y[i]);
    }
    vector<vector<int>> B(M, vector<int>(N));
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j <= R[i]; j++){
        B[i][j] = lower_bound(Y[j].begin(), Y[j].end(), A[i][j] - eps) - Y[j].begin();
      }
    }
    E.resize(N - 1);
    for (int i = 0; i < N - 1; i++){
      E[i].push_back(make_tuple(-1, -1, e));
    }
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j < R[i]; j++){
        E[j].push_back(make_tuple(B[i][j], B[i][j + 1], S[i].second));
      }
    }
    for (int i = 0; i < N - 1; i++){
      E[i].push_back(make_tuple(Y[i].size(), Y[i + 1].size(), e));
    }
    for (int i = 0; i < N - 1; i++){
      sort(E[i].begin(), E[i].end());
      if (!E[i].empty()){
        vector<tuple<int, int, T>> E2;
        int cnt = E[i].size();
        E2.push_back(E[i][0]);
        for (int j = 1; j < cnt; j++){
          if (get<0>(E[i][j - 1]) == get<0>(E[i][j]) && get<1>(E[i][j - 1]) == get<1>(E[i][j])){
            get<2>(E2.back()) = f(get<2>(E2.back()), get<2>(E[i][j]));
          } else {
            E2.push_back(E[i][j]);
          }
        }
        E[i] = E2;
      }
    }
    P.resize(N + 2);
    P[0] = 0;
    P[1] = 1;
    for (int i = 0; i < N - 1; i++){
      P[i + 2] = P[i + 1] + E[i].size() - 1;
    }
    P[N + 1] = P[N] + 1;
    vector<vector<int>> idL(N), idR(N);
    for (int i = 0; i < N; i++){
      idL[i] = vector<int>(Y[i].size() + 1);
      idR[i] = vector<int>(Y[i].size() + 1);
    }
    idL[0] = vector<int>(Y[0].size() + 1, 0);
    for (int i = 0; i < N - 1; i++){
      int cnt = E[i].size();
      for (int j = 0; j < cnt - 1; j++){
        for (int k = get<0>(E[i][j]) + 1; k <= get<0>(E[i][j + 1]); k++){
          idR[i][k] = P[i + 1] + j;
        }
        for (int k = get<1>(E[i][j]) + 1; k <= get<1>(E[i][j + 1]); k++){
          idL[i + 1][k] = P[i + 1] + j;
        }
      }
    }
    idR[N - 1] = vector<int>(Y[N - 1].size() + 1, P[N]);
    int V = P[N + 1];
    vector<vector<pair<T, int>>> G(V);
    for (int i = 0; i <= N; i++){
      for (int j = P[i]; j < P[i + 1] - 1; j++){
        G[j].push_back(make_pair(get<2>(E[i - 1][j - P[i] + 1]), j + 1));
        G[j + 1].push_back(make_pair(get<2>(E[i - 1][j - P[i] + 1]), j));
      }
    }
    for (int i = 0; i < N; i++){
      for (int j = 0; j <= Y[i].size(); j++){
        G[idL[i][j]].push_back(make_pair(e, idR[i][j]));
        G[idR[i][j]].push_back(make_pair(e, idL[i][j]));
      }
    }
    return G;
  }
  int find(point p){
    int x = lower_bound(X.begin(), X.end(), p.x - eps) - X.begin();
    if (x == 0){
      return 0;
    } else if (x == N){
      return P[N];
    } else {
      int ans = P[x];
      for (int i = 1; i < E[x - 1].size() - 1; i++){
        point A(X[x - 1], Y[x - 1][get<0>(E[x - 1][i])]);
        point B(X[x], Y[x][get<1>(E[x - 1][i])]);
        if (cross(B - A, p - A) > 0){
          ans++;
        }
      }
      return ans;
    }
  }
  vector<double> area(){
    int V = P[N + 1];
    vector<double> ans(V, -1);
    for (int i = 0; i < N - 1; i++){
      for(int j = 1; j < E[i].size() - 2; j++){
        double l = Y[i][get<0>(E[i][j + 1])] - Y[i][get<0>(E[i][j])];
        double r = Y[i + 1][get<1>(E[i][j + 1])] - Y[i + 1][get<1>(E[i][j])];
        ans[P[i + 1] + j] = (l + r) * (X[i + 1] - X[i]) / 2;
      }
    }
    return ans;
  }
  vector<double> length(){
    int V = P[N + 1];
    vector<double> ans(V, -1);
    for (int i = 0; i < N - 1; i++){
      for(int j = 1; j < E[i].size() - 1; j++){
        double l = Y[i][get<0>(E[i][j])];
        double r = Y[i + 1][get<1>(E[i][j])];
        ans[P[i + 1] + j - 1] = hypot(X[i + 1] - X[i], r - l);
      }
    }
    return ans;
  }
};
int main(){
  while (true){
    int C, W;
    cin >> C >> W;
    if (C == 0 && W == 0){
      break;
    }
    vector<point> P(C);
    for (int i = 0; i < C; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<int> s(W), t(W);
    for (int i = 0; i < W; i++){
      cin >> s[i] >> t[i];
      s[i]--;
      t[i]--;
    }
    for (int i = 0; i < C; i++){
      P[i] = rotate(P[i], 1);
    }
    slab_decomposition<bool> D(logical_or<>(), false);
    for (int i = 0; i < W; i++){
      D.add_segment(line(P[s[i]], P[t[i]]), true);
    }
    vector<vector<pair<bool, int>>> E = D.build();
    int V = E.size();
    vector<int> d(V, -1);
    deque<pair<int, int>> dq;
    dq.push_back(make_pair(0, 0));
    while (!dq.empty()){
      int c = dq.front().first;
      int v = dq.front().second;
      dq.pop_front();
      if (d[v] == -1){
        d[v] = c;
        for (pair<int, int> e : E[v]){
          int w = e.second;
          if (d[w] == -1){
            if (!e.first){
              dq.push_front(make_pair(c, w));
            } else {
              dq.push_back(make_pair(c + 1, w));
            }
          }
        }
      }
    }
    int ans = 0;
    for (int i = 0; i < V; i++){
      ans = max(ans, d[i]);
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 20
memory_kb: 4216
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double eps = 0.00001;
int sign(double x){
  if (x > eps){
    return 1;
  } else if (x < -eps){
    return -1;
  } else {
    return 0;
  }
}
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
  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 k){
    return point(x * k, y * k);
  }
  point operator /(double k){
    return point(x / k, y / k);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
double dist(point P, point Q){
  return abs(Q - P);
}
point rotate(point P, double t){
  return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t));
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
bool is_parallel(line L1, line L2){
  return abs(cross(vec(L1), vec(L2))) < eps;
}
bool segment_line_intersect(line L1, line L2){
  return sign(cross(L1.A - L2.A, vec(L2))) * sign(cross(L1.B - L2.A, vec(L2))) <= 0;
}
bool segment_intersect(line L1, line L2){
  return segment_line_intersect(L1, L2) && segment_line_intersect(L2, L1);
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
vector<double> unique_eps(vector<double> A){
  int N = A.size();
  sort(A.begin(), A.end());
  vector<double> A2;
  A2.push_back(A[0]);
  for (int i = 1; i < N; i++){
    if (A[i] - A[i - 1] > eps){
      A2.push_back(A[i]);
    }
  }
  return A2;
}
struct slab_decomposition{
  vector<line> S;
  slab_decomposition(){
  }
  void add_segment(line s){
    S.push_back(s);
  }
  vector<vector<pair<int, int>>> build(){
    int M = S.size();
    for (int i = 0; i < M; i++){
      if (S[i].A.x > S[i].B.x){
        swap(S[i].A, S[i].B);
      }
    }
    vector<double> X;
    for (int i = 0; i < M; i++){
      X.push_back(S[i].A.x);
      X.push_back(S[i].B.x);
    }
    for (int i = 0; i < M; i++){
      for (int j = i + 1; j < M; j++){
        if (!is_parallel(S[i], S[j]) && segment_intersect(S[i], S[j])){
          X.push_back(line_intersection(S[i], S[j]).x);
        }
      }
    }
    X = unique_eps(X);
    int N = X.size();
    vector<int> L(M), R(M);
    for (int i = 0; i < M; i++){
      L[i] = lower_bound(X.begin(), X.end(), S[i].A.x - eps) - X.begin();
      R[i] = lower_bound(X.begin(), X.end(), S[i].B.x - eps) - X.begin();
    }
    vector<vector<double>> A(M, vector<double>(N));
    vector<vector<double>> Y(N);
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j <= R[i]; j++){
        A[i][j] = line_intersection(S[i], line(point(X[j], 0), point(X[j], 1))).y;
        Y[j].push_back(A[i][j]);
      }
    }
    for (int i = 0; i < N; i++){
      Y[i] = unique_eps(Y[i]);
    }
    vector<vector<int>> B(M, vector<int>(N));
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j <= R[i]; j++){
        B[i][j] = lower_bound(Y[j].begin(), Y[j].end(), A[i][j] - eps) - Y[j].begin();
      }
    }
    vector<vector<pair<int, int>>> E(N - 1);
    for (int i = 0; i < N - 1; i++){
      E[i].push_back(make_pair(-1, -1));
    }
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j < R[i]; j++){
        E[j].push_back(make_pair(B[i][j], B[i][j + 1]));
      }
    }
    for (int i = 0; i < N - 1; i++){
      E[i].push_back(make_pair(Y[i].size(), Y[i + 1].size()));
    }
    for (int i = 0; i < N - 1; i++){
      sort(E[i].begin(), E[i].end());
    }
    vector<int> S(N + 2);
    S[0] = 0;
    S[1] = 1;
    for (int i = 0; i < N - 1; i++){
      S[i + 2] = S[i + 1] + E[i].size() - 1;
    }
    S[N + 1] = S[N] + 1;
    vector<vector<int>> idL(N), idR(N);
    for (int i = 0; i < N; i++){
      idL[i] = vector<int>(Y[i].size() + 1);
      idR[i] = vector<int>(Y[i].size() + 1);
    }
    idL[0] = vector<int>(Y[0].size() + 1, 0);
    for (int i = 0; i < N - 1; i++){
      int cnt = E[i].size();
      for (int j = 0; j < cnt - 1; j++){
        for (int k = E[i][j].first + 1; k <= E[i][j + 1].first; k++){
          idR[i][k] = S[i + 1] + j;
        }
        for (int k = E[i][j].second + 1; k <= E[i][j + 1].second; k++){
          idL[i + 1][k] = S[i + 1] + j;
        }
      }
    }
    idR[N - 1] = vector<int>(Y[N - 1].size() + 1, S[N]);
    int V = S[N + 1];
    vector<vector<pair<int, int>>> G(V);
    for (int i = 0; i <= N; i++){
      for (int j = S[i]; j < S[i + 1] - 1; j++){
        G[j].push_back(make_pair(1, j + 1));
        G[j + 1].push_back(make_pair(1, j));
      }
    }
    for (int i = 0; i < N; i++){
      for (int j = 0; j <= Y[i].size(); j++){
        G[idL[i][j]].push_back(make_pair(0, idR[i][j]));
        G[idR[i][j]].push_back(make_pair(0, idL[i][j]));
      }
    }
    return G;
  }
};
int main(){
  while (true){
    int C, W;
    cin >> C >> W;
    if (C == 0 && W == 0){
      break;
    }
    vector<point> P(C);
    for (int i = 0; i < C; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<int> s(W), t(W);
    for (int i = 0; i < W; i++){
      cin >> s[i] >> t[i];
      s[i]--;
      t[i]--;
    }
    for (int i = 0; i < C; i++){
      P[i] = rotate(P[i], 1);
    }
    slab_decomposition D;
    for (int i = 0; i < W; i++){
      D.add_segment(line(P[s[i]], P[t[i]]));
    }
    vector<vector<pair<int, int>>> E = D.build();
    int V = E.size();
    vector<int> d(V, -1);
    deque<pair<int, int>> dq;
    dq.push_back(make_pair(0, 0));
    while (!dq.empty()){
      int c = dq.front().first;
      int v = dq.front().second;
      dq.pop_front();
      if (d[v] == -1){
        d[v] = c;
        for (pair<int, int> e : E[v]){
          int w = e.second;
          if (d[w] == -1){
            if (e.first == 0){
              dq.push_front(make_pair(c, w));
            }
            if (e.first == 1){
              dq.push_back(make_pair(c + 1, w));
            }
          }
        }
      }
    }
    int ans = 0;
    for (int i = 0; i < V; i++){
      ans = max(ans, d[i]);
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 20
memory_kb: 4100
final_rank: 9

code_snippet: #include <bits/stdc++.h>
using namespace std;
const double eps = 0.00001;
int sign(double x){
  if (x > eps){
    return 1;
  } else if (x < -eps){
    return -1;
  } else {
    return 0;
  }
}
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
  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 k){
    return point(x * k, y * k);
  }
  point operator /(double k){
    return point(x / k, y / k);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
double dist(point P, point Q){
  return abs(Q - P);
}
point rotate(point P, double t){
  return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t));
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(){
  }
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
bool is_parallel(line L1, line L2){
  return abs(cross(vec(L1), vec(L2))) < eps;
}
bool segment_line_intersect(line L1, line L2){
  return sign(cross(L1.A - L2.A, vec(L2))) * sign(cross(L1.B - L2.A, vec(L2))) <= 0;
}
bool segment_intersect(line L1, line L2){
  return segment_line_intersect(L1, L2) && segment_line_intersect(L2, L1);
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
vector<double> unique_eps(vector<double> A){
  int N = A.size();
  sort(A.begin(), A.end());
  vector<double> A2;
  A2.push_back(A[0]);
  for (int i = 1; i < N; i++){
    if (A[i] - A[i - 1] > eps){
      A2.push_back(A[i]);
    }
  }
  return A2;
}
struct slab_decomposition{
  vector<line> S;
  vector<double> X;
  vector<vector<double>> Y;
  slab_decomposition(){
  }
  void add_segment(line s){
    S.push_back(s);
  }
  vector<vector<pair<int, int>>> build(){
    int M = S.size();
    for (int i = 0; i < M; i++){
      if (S[i].A.x > S[i].B.x){
        swap(S[i].A, S[i].B);
      }
    }
    for (int i = 0; i < M; i++){
      X.push_back(S[i].A.x);
      X.push_back(S[i].B.x);
    }
    for (int i = 0; i < M; i++){
      for (int j = i + 1; j < M; j++){
        if (!is_parallel(S[i], S[j]) && segment_intersect(S[i], S[j])){
          X.push_back(line_intersection(S[i], S[j]).x);
        }
      }
    }
    X = unique_eps(X);
    int N = X.size();
    vector<int> L(M), R(M);
    for (int i = 0; i < M; i++){
      L[i] = lower_bound(X.begin(), X.end(), S[i].A.x - eps) - X.begin();
      R[i] = lower_bound(X.begin(), X.end(), S[i].B.x - eps) - X.begin();
    }
    vector<vector<double>> A(M, vector<double>(N));
    vector<vector<double>> Y(N);
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j <= R[i]; j++){
        A[i][j] = line_intersection(S[i], line(point(X[j], 0), point(X[j], 1))).y;
        Y[j].push_back(A[i][j]);
      }
    }
    for (int i = 0; i < N; i++){
      Y[i] = unique_eps(Y[i]);
    }
    vector<vector<int>> B(M, vector<int>(N));
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j <= R[i]; j++){
        B[i][j] = lower_bound(Y[j].begin(), Y[j].end(), A[i][j] - eps) - Y[j].begin();
      }
    }
    vector<vector<pair<int, int>>> E(N - 1);
    for (int i = 0; i < N - 1; i++){
      E[i].push_back(make_pair(-1, -1));
    }
    for (int i = 0; i < M; i++){
      for (int j = L[i]; j < R[i]; j++){
        E[j].push_back(make_pair(B[i][j], B[i][j + 1]));
      }
    }
    for (int i = 0; i < N - 1; i++){
      E[i].push_back(make_pair(Y[i].size(), Y[i + 1].size()));
    }
    for (int i = 0; i < N - 1; i++){
      sort(E[i].begin(), E[i].end());
    }
    vector<int> S(N + 2);
    S[0] = 0;
    S[1] = 1;
    for (int i = 0; i < N - 1; i++){
      S[i + 2] = S[i + 1] + E[i].size() - 1;
    }
    S[N + 1] = S[N] + 1;
    vector<vector<int>> idL(N), idR(N);
    for (int i = 0; i < N; i++){
      idL[i] = vector<int>(Y[i].size() + 1);
      idR[i] = vector<int>(Y[i].size() + 1);
    }
    idL[0] = vector<int>(Y[0].size() + 1, 0);
    for (int i = 0; i < N - 1; i++){
      int cnt = E[i].size();
      for (int j = 0; j < cnt - 1; j++){
        for (int k = E[i][j].first + 1; k <= E[i][j + 1].first; k++){
          idR[i][k] = S[i + 1] + j;
        }
        for (int k = E[i][j].second + 1; k <= E[i][j + 1].second; k++){
          idL[i + 1][k] = S[i + 1] + j;
        }
      }
    }
    idR[N - 1] = vector<int>(Y[N - 1].size() + 1, S[N]);
    int V = S[N + 1];
    vector<vector<pair<int, int>>> G(V);
    for (int i = 0; i <= N; i++){
      for (int j = S[i]; j < S[i + 1] - 1; j++){
        G[j].push_back(make_pair(1, j + 1));
        G[j + 1].push_back(make_pair(1, j));
      }
    }
    for (int i = 0; i < N; i++){
      for (int j = 0; j <= Y[i].size(); j++){
        G[idL[i][j]].push_back(make_pair(0, idR[i][j]));
        G[idR[i][j]].push_back(make_pair(0, idL[i][j]));
      }
    }
    return G;
  }
};
int main(){
  while (true){
    int C, W;
    cin >> C >> W;
    if (C == 0 && W == 0){
      break;
    }
    vector<point> P(C);
    for (int i = 0; i < C; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<int> s(W), t(W);
    for (int i = 0; i < W; i++){
      cin >> s[i] >> t[i];
      s[i]--;
      t[i]--;
    }
    for (int i = 0; i < C; i++){
      P[i] = rotate(P[i], 1);
    }
    slab_decomposition D;
    for (int i = 0; i < W; i++){
      D.add_segment(line(P[s[i]], P[t[i]]));
    }
    vector<vector<pair<int, int>>> E = D.build();
    int V = E.size();
    vector<int> d(V, -1);
    deque<pair<int, int>> dq;
    dq.push_back(make_pair(0, 0));
    while (!dq.empty()){
      int c = dq.front().first;
      int v = dq.front().second;
      dq.pop_front();
      if (d[v] == -1){
        d[v] = c;
        for (pair<int, int> e : E[v]){
          int w = e.second;
          if (d[w] == -1){
            if (e.first == 0){
              dq.push_front(make_pair(c, w));
            }
            if (e.first == 1){
              dq.push_back(make_pair(c + 1, w));
            }
          }
        }
      }
    }
    int ans = 0;
    for (int i = 0; i < V; i++){
      ans = max(ans, d[i]);
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 20
memory_kb: 4236
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
};
point rotate(point P, double t){
  return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t));
}
int main(){
  while (true){
    int N, M;
    cin >> N >> M;
    if (N == 0 && M == 0){
      break;
    }
    vector<point> P(N);
    for (int i = 0; i < N; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<int> s(M), t(M);
    for (int i = 0; i < M; i++){
      cin >> s[i] >> t[i];
      s[i]--;
      t[i]--;
    }
    for (int i = 0; i < N; i++){
      P[i] = rotate(P[i], 0.01);
    }
    vector<double> X;
    for (int i = 0; i < N; i++){
      X.push_back(P[i].x);
    }
    sort(X.begin(), X.end());
    vector<int> l(M), r(M);
    for (int i = 0; i < M; i++){
      if (P[s[i]].x > P[t[i]].x){
        swap(s[i], t[i]);
      }
      l[i] = lower_bound(X.begin(), X.end(), P[s[i]].x) - X.begin();
      r[i] = lower_bound(X.begin(), X.end(), P[t[i]].x) - X.begin();
    }
    vector<vector<double>> Y(M, vector<double>(N));
    for (int i = 0; i < M; i++){
      Y[i][l[i]] = P[s[i]].y;
      for (int j = l[i] + 1; j < r[i]; j++){
        Y[i][j] = P[s[i]].y + (P[t[i]].y - P[s[i]].y) * (X[j] - X[l[i]]) / (X[r[i]] - X[l[i]]);
      }
      Y[i][r[i]] = P[t[i]].y;
    }
    vector<vector<double>> Y2(N);
    for (int i = 0; i < M; i++){
      for (int j = l[i]; j <= r[i]; j++){
        Y2[j].push_back(Y[i][j]);
      }
    }
    for (int i = 0; i < N; i++){
      sort(Y2[i].begin(), Y2[i].end());
      Y2[i].erase(unique(Y2[i].begin(), Y2[i].end()), Y2[i].end());
    }
    vector<int> YC(N);
    for (int i = 0; i < N; i++){
      YC[i] = Y2[i].size();
    }
    vector<vector<int>> A(M, vector<int>(N));
    for (int i = 0; i < M; i++){
      for (int j = l[i]; j <= r[i]; j++){
        A[i][j] = lower_bound(Y2[j].begin(), Y2[j].end(), Y[i][j]) - Y2[j].begin();
      }
    }
    vector<vector<pair<int, int>>> C(N - 1);
    for (int i = 0; i < N - 1; i++){
      C[i].push_back(make_pair(-1, -1));
    }
    for (int i = 0; i < M; i++){
      for (int j = l[i]; j < r[i]; j++){
        C[j].push_back(make_pair(A[i][j], A[i][j + 1]));
      }
    }
    for (int i = 0; i < N - 1; i++){
      C[i].push_back(make_pair(YC[i], YC[i + 1]));
    }
    for (int i = 0; i < N - 1; i++){
      sort(C[i].begin(), C[i].end());
    }
    vector<int> S(N + 2);
    S[0] = 0;
    S[1] = 1;
    for (int i = 0; i < N - 1; i++){
      S[i + 2] = S[i + 1] + C[i].size() - 1;
    }
    S[N + 1] = S[N] + 1;
    vector<vector<int>> idL(N), idR(N);
    for (int i = 0; i < N; i++){
      idL[i] = vector<int>(YC[i] + 1);
      idR[i] = vector<int>(YC[i] + 1);
    }
    idL[0] = vector<int>(YC[0] + 1, 0);
    for (int i = 0; i < N - 1; i++){
      int cnt = C[i].size();
      for (int j = 0; j < cnt - 1; j++){
        for (int k = C[i][j].first + 1; k <= C[i][j + 1].first; k++){
          idR[i][k] = S[i + 1] + j;
        }
        for (int k = C[i][j].second + 1; k <= C[i][j + 1].second; k++){
          idL[i + 1][k] = S[i + 1] + j;
        }
      }
    }
    idR[N - 1] = vector<int>(YC[N - 1] + 1, S[N]);
    int V = S[N + 1];
    vector<vector<pair<int, int>>> E(V);
    for (int i = 0; i <= N; i++){
      for (int j = S[i]; j < S[i + 1] - 1; j++){
        E[j].push_back(make_pair(1, j + 1));
        E[j + 1].push_back(make_pair(1, j));
      }
    }
    for (int i = 0; i < N; i++){
      for (int j = 0; j <= YC[i]; j++){
        E[idL[i][j]].push_back(make_pair(0, idR[i][j]));
        E[idR[i][j]].push_back(make_pair(0, idL[i][j]));
      }
    }
    vector<int> d(V, -1);
    deque<pair<int, int>> dq;
    dq.push_back(make_pair(0, 0));
    while (!dq.empty()){
      int c = dq.front().first;
      int v = dq.front().second;
      dq.pop_front();
      if (d[v] == -1){
        d[v] = c;
        for (pair<int, int> e : E[v]){
          int w = e.second;
          if (d[w] == -1){
            if (e.first == 0){
              dq.push_front(make_pair(c, w));
            }
            if (e.first == 1){
              dq.push_back(make_pair(c + 1, w));
            }
          }
        }
      }
    }
    int ans = 0;
    for (int i = 0; i < V; i++){
      ans = max(ans, d[i]);
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 4200
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
};
point rotate(point P, double t){
  return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t));
}
int main(){
  while (true){
    int N, M;
    cin >> N >> M;
    if (N == 0 && M == 0){
      break;
    }
    vector<point> P(N);
    for (int i = 0; i < N; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<int> s(M), t(M);
    for (int i = 0; i < M; i++){
      cin >> s[i] >> t[i];
      s[i]--;
      t[i]--;
    }
    for (int i = 0; i < N; i++){
      P[i] = rotate(P[i], 0.01);
    }
    vector<double> X;
    for (int i = 0; i < N; i++){
      X.push_back(P[i].x);
    }
    sort(X.begin(), X.end());
    vector<int> l(M), r(M);
    for (int i = 0; i < M; i++){
      if (P[s[i]].x > P[t[i]].x){
        swap(s[i], t[i]);
      }
      l[i] = lower_bound(X.begin(), X.end(), P[s[i]].x) - X.begin();
      r[i] = lower_bound(X.begin(), X.end(), P[t[i]].x) - X.begin();
    }
    vector<vector<double>> Y(M, vector<double>(N));
    for (int i = 0; i < M; i++){
      Y[i][l[i]] = P[s[i]].y;
      for (int j = l[i] + 1; j < r[i]; j++){
        Y[i][j] = P[s[i]].y + (P[t[i]].y - P[s[i]].y) * (X[j] - X[l[i]]) / (X[r[i]] - X[l[i]]);
      }
      Y[i][r[i]] = P[t[i]].y;
    }
    vector<vector<double>> Y2(N);
    for (int i = 0; i < M; i++){
      for (int j = l[i]; j <= r[i]; j++){
        Y2[j].push_back(Y[i][j]);
      }
    }
    for (int i = 0; i < N; i++){
      sort(Y2[i].begin(), Y2[i].end());
      Y2[i].erase(unique(Y2[i].begin(), Y2[i].end()), Y2[i].end());
    }
    vector<vector<int>> A(M, vector<int>(N));
    for (int i = 0; i < M; i++){
      for (int j = l[i]; j <= r[i]; j++){
        A[i][j] = lower_bound(Y2[j].begin(), Y2[j].end(), Y[i][j]) - Y2[j].begin();
      }
    }
    vector<vector<pair<int, int>>> C(N - 1);
    for (int i = 0; i < M; i++){
      for (int j = l[i]; j < r[i]; j++){
        C[j].push_back(make_pair(A[i][j], A[i][j + 1]));
      }
    }
    for (int i = 0; i < N - 1; i++){
      sort(C[i].begin(), C[i].end());
    }
    vector<int> YC(N);
    for (int i = 0; i < N; i++){
      YC[i] = Y2[i].size();
    }
    vector<int> S(N + 2);
    S[0] = 0;
    S[1] = 1;
    for (int i = 0; i < N - 1; i++){
      S[i + 2] = S[i + 1] + C[i].size() + 1;
    }
    S[N + 1] = S[N] + 1;
    vector<vector<int>> idL(N), idR(N);
    for (int i = 0; i < N; i++){
      idL[i] = vector<int>(YC[i] + 1);
      idR[i] = vector<int>(YC[i] + 1);
    }
    idL[0] = vector<int>(YC[0] + 1, 0);
    for (int i = 0; i < N - 1; i++){
      vector<pair<int, int>> C2 = C[i];
      C2.insert(C2.begin(), make_pair(-1, -1));
      C2.push_back(make_pair(YC[i], YC[i + 1]));
      int cnt = C2.size();
      for (int j = 0; j < cnt - 1; j++){
        for (int k = C2[j].first + 1; k <= C2[j + 1].first; k++){
          idR[i][k] = S[i + 1] + j;
        }
        for (int k = C2[j].second + 1; k <= C2[j + 1].second; k++){
          idL[i + 1][k] = S[i + 1] + j;
        }
      }
    }
    idR[N - 1] = vector<int>(YC[N - 1] + 1, S[N]);
    int V = S[N + 1];
    vector<vector<pair<int, int>>> E(V);
    for (int i = 0; i <= N; i++){
      for (int j = S[i]; j < S[i + 1] - 1; j++){
        E[j].push_back(make_pair(1, j + 1));
        E[j + 1].push_back(make_pair(1, j));
      }
    }
    for (int i = 0; i < N; i++){
      for (int j = 0; j <= YC[i]; j++){
        E[idL[i][j]].push_back(make_pair(0, idR[i][j]));
        E[idR[i][j]].push_back(make_pair(0, idL[i][j]));
      }
    }
    vector<int> d(V, -1);
    deque<pair<int, int>> dq;
    dq.push_back(make_pair(0, 0));
    while (!dq.empty()){
      int c = dq.front().first;
      int v = dq.front().second;
      dq.pop_front();
      if (d[v] == -1){
        d[v] = c;
        for (pair<int, int> e : E[v]){
          int w = e.second;
          if (d[w] == -1){
            if (e.first == 0){
              dq.push_front(make_pair(c, w));
            }
            if (e.first == 1){
              dq.push_back(make_pair(c + 1, w));
            }
          }
        }
      }
    }
    int ans = 0;
    for (int i = 0; i < V; i++){
      ans = max(ans, d[i]);
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 4312
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
  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 k){
    return point(x * k, y * k);
  }
  point operator /(double k){
    return point(x / k, y / k);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
point rotate(point P, double t){
  return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t));
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
int main(){
  while (true){
    int C, W;
    cin >> C >> W;
    if (C == 0 && W == 0){
      break;
    }
    vector<point> P(C);
    for (int i = 0; i < C; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<int> s(W), t(W);
    for (int i = 0; i < W; i++){
      cin >> s[i] >> t[i];
      s[i]--;
      t[i]--;
    }
    for (int i = 0; i < C; i++){
      P[i] = rotate(P[i], 0.01);
    }
    vector<double> X;
    for (int i = 0; i < C; i++){
      X.push_back(P[i].x);
    }
    sort(X.begin(), X.end());    
    for (int i = 0; i < W; i++){
      if (P[s[i]].x > P[t[i]].x){
        swap(s[i], t[i]);
      }
    }
    vector<int> l(W), r(W);
    for (int i = 0; i < W; i++){
      l[i] = lower_bound(X.begin(), X.end(), P[s[i]].x) - X.begin();
      r[i] = lower_bound(X.begin(), X.end(), P[t[i]].x) - X.begin();
    }
    vector<vector<pair<int, double>>> y(W);
    for (int i = 0; i < W; i++){
      y[i].push_back(make_pair(l[i], P[s[i]].y));
      line L(P[s[i]], P[t[i]]);
      for (int j = l[i] + 1; j < r[i]; j++){
        line L2(point(X[j], 0), point(X[j], 1));
        y[i].push_back(make_pair(j, line_intersection(L, L2).y));
      }
      y[i].push_back(make_pair(r[i], P[t[i]].y));
    }
    vector<vector<double>> y2(C);
    for (int i = 0; i < W; i++){
      int cnt = y[i].size();
      for (int j = 0; j < cnt; j++){
        int id = y[i][j].first;
        double p = y[i][j].second;
        y2[id].push_back(p);
      }
    }
    for (int i = 0; i < C; i++){
      sort(y2[i].begin(), y2[i].end());
      y2[i].erase(unique(y2[i].begin(), y2[i].end()), y2[i].end());
    }
    vector<vector<pair<int, int>>> e(C - 1);
    for (int i = 0; i < W; i++){
      vector<int> id(r[i] - l[i] + 1);
      for (int j = l[i]; j <= r[i]; j++){
        id[j - l[i]] = lower_bound(y2[j].begin(), y2[j].end(), y[i][j - l[i]].second) - y2[j].begin();
      }
      for (int j = 0; j < r[i] - l[i]; j++){
        e[l[i] + j].push_back(make_pair(id[j], id[j + 1]));
      }
    }
    for (int i = 0; i < C - 1; i++){
      sort(e[i].begin(), e[i].end());
    }
    vector<int> S(C + 2);
    S[0] = 0;
    S[1] = 1;
    for (int i = 0; i < C - 1; i++){
      S[i + 2] = S[i + 1] + e[i].size() + 1;
    }
    S[C + 1] = S[C] + 1;
    vector<int> T(C + 1);
    T[0] = S[C + 1];
    for (int i = 0; i < C; i++){
      T[i + 1] = T[i] + y2[i].size() + 1;
    }
    vector<vector<pair<int, int>>> E(T[C]);
    for (int i = 0; i <= C; i++){
      for (int j = S[i]; j < S[i + 1] - 1; j++){
        E[j].push_back(make_pair(1, j + 1));
        E[j + 1].push_back(make_pair(1, j));
      }
    }
    for (int i = 0; i < C; i++){
      if (i == 0){
        int cnt = y2[i].size();
        for (int j = 0; j <= cnt; j++){
          E[S[0]].push_back(make_pair(0, T[0] + j));
          E[T[0] + j].push_back(make_pair(0, S[0]));
        }
      }
      if (i > 0){
        E[S[i]].push_back(make_pair(0, T[i]));
        E[T[i]].push_back(make_pair(0, S[i]));
        int cnt = e[i - 1].size();
        for (int j = 0; j < cnt - 1; j++){
          for (int k = e[i - 1][j].second + 1; k <= e[i - 1][j + 1].second; k++){
            E[S[i] + j + 1].push_back(make_pair(0, T[i] + k));
            E[T[i] + k].push_back(make_pair(0, S[i] + j + 1));
          }
        }
        for (int k = e[i - 1][cnt - 1].second + 1; k <= y2[i].size(); k++){
          E[S[i] + cnt].push_back(make_pair(0, T[i] + k));
          E[T[i] + k].push_back(make_pair(0, S[i] + cnt));
        }
      }
      if (i < C - 1){
        E[S[i + 1]].push_back(make_pair(0, T[i]));
        E[T[i]].push_back(make_pair(0, S[i + 1]));
        int cnt = e[i].size();
        for (int j = 0; j < cnt - 1; j++){
          for (int k = e[i][j].first + 1; k <= e[i][j + 1].first; k++){
            E[S[i + 1] + j + 1].push_back(make_pair(0, T[i] + k));
            E[T[i] + k].push_back(make_pair(0, S[i + 1] + j + 1));
          }
        }
        for (int k = e[i][cnt - 1].first + 1; k <= y2[i].size(); k++){
          E[S[i + 1] + cnt].push_back(make_pair(0, T[i] + k));
          E[T[i] + k].push_back(make_pair(0, S[i + 1] + cnt));
        }
      }
      if (i == C - 1){
        int cnt = y2[i].size();
        for (int j = 0; j <= cnt; j++){
          E[S[i + 1]].push_back(make_pair(0, T[i] + j));
          E[T[i] + j].push_back(make_pair(0, S[i + 1]));
        }
      }
    }
    vector<int> d(T[C], -1);
    deque<pair<int, int>> dq;
    dq.push_back(make_pair(0, 0));
    while (!dq.empty()){
      int c = dq.front().first;
      int v = dq.front().second;
      dq.pop_front();
      if (d[v] == -1){
        d[v] = c;
        for (auto p : E[v]){
          int w = p.second;
          if (d[w] == -1){
            if (p.first == 0){
              dq.push_front(make_pair(c, w));
            }
            if (p.first == 1){
              dq.push_back(make_pair(c + 1, w));
            }
          }
        }
      }
    }
    int ans = 0;
    for (int i = 0; i < T[C]; i++){
      ans = max(ans, d[i]);
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3980
final_rank: 3

code_snippet: #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
  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 k){
    return point(x * k, y * k);
  }
  point operator /(double k){
    return point(x / k, y / k);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
point rotate(point P, double t){
  return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t));
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
int main(){
  while (true){
    int C, W;
    cin >> C >> W;
    if (C == 0 && W == 0){
      break;
    }
    vector<point> P(C);
    for (int i = 0; i < C; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<int> s(W), t(W);
    for (int i = 0; i < W; i++){
      cin >> s[i] >> t[i];
      s[i]--;
      t[i]--;
    }
    for (int i = 0; i < C; i++){
      P[i] = rotate(P[i], 0.01);
    }
    vector<double> X;
    for (int i = 0; i < C; i++){
      X.push_back(P[i].x);
    }
    sort(X.begin(), X.end());    
    for (int i = 0; i < W; i++){
      if (P[s[i]].x > P[t[i]].x){
        swap(s[i], t[i]);
      }
    }
    vector<int> l(W), r(W);
    for (int i = 0; i < W; i++){
      l[i] = lower_bound(X.begin(), X.end(), P[s[i]].x) - X.begin();
      r[i] = lower_bound(X.begin(), X.end(), P[t[i]].x) - X.begin();
    }
    vector<vector<pair<int, double>>> y(W);
    for (int i = 0; i < W; i++){
      y[i].push_back(make_pair(l[i], P[s[i]].y));
      line L(P[s[i]], P[t[i]]);
      for (int j = l[i] + 1; j < r[i]; j++){
        line L2(point(X[j], 0), point(X[j], 1));
        y[i].push_back(make_pair(j, line_intersection(L, L2).y));
      }
      y[i].push_back(make_pair(r[i], P[t[i]].y));
    }
    vector<vector<double>> y2(C);
    for (int i = 0; i < W; i++){
      int cnt = y[i].size();
      for (int j = 0; j < cnt; j++){
        int id = y[i][j].first;
        double p = y[i][j].second;
        y2[id].push_back(p);
      }
    }
    for (int i = 0; i < C; i++){
      sort(y2[i].begin(), y2[i].end());
      y2[i].erase(unique(y2[i].begin(), y2[i].end()), y2[i].end());
    }
    vector<vector<pair<int, int>>> e(C - 1);
    for (int i = 0; i < W; i++){
      vector<int> id(r[i] - l[i] + 1);
      for (int j = l[i]; j <= r[i]; j++){
        id[j - l[i]] = lower_bound(y2[j].begin(), y2[j].end(), y[i][j - l[i]].second) - y2[j].begin();
      }
      for (int j = 0; j < r[i] - l[i]; j++){
        e[l[i] + j].push_back(make_pair(id[j], id[j + 1]));
      }
    }
    for (int i = 0; i < C - 1; i++){
      sort(e[i].begin(), e[i].end());
    }
    vector<int> S(C + 2);
    S[0] = 0;
    S[1] = 1;
    for (int i = 0; i < C - 1; i++){
      S[i + 2] = S[i + 1] + e[i].size() + 1;
    }
    S[C + 1] = S[C] + 1;
    vector<int> T(C + 1);
    T[0] = S[C + 1];
    for (int i = 0; i < C; i++){
      T[i + 1] = T[i] + y2[i].size() + 1;
    }
    vector<vector<pair<int, int>>> E(T[C]);
    for (int i = 0; i <= C; i++){
      for (int j = S[i]; j < S[i + 1] - 1; j++){
        E[j].push_back(make_pair(1, j + 1));
        E[j + 1].push_back(make_pair(1, j));
      }
    }
    for (int i = 0; i < C; i++){
      if (i == 0){
        int cnt = y2[i].size();
        for (int j = 0; j <= cnt; j++){
          E[S[0]].push_back(make_pair(0, T[0] + j));
          E[T[0] + j].push_back(make_pair(0, S[0]));
        }
      }
      if (i > 0){
        E[S[i]].push_back(make_pair(0, T[i]));
        E[T[i]].push_back(make_pair(0, S[i]));
        int cnt = e[i - 1].size();
        for (int j = 0; j < cnt - 1; j++){
          for (int k = e[i - 1][j].second + 1; k <= e[i - 1][j + 1].second; k++){
            E[S[i] + j + 1].push_back(make_pair(0, T[i] + k));
            E[T[i] + k].push_back(make_pair(0, S[i] + j + 1));
          }
        }
        for (int k = e[i - 1][cnt - 1].second + 1; k <= y2[i].size(); k++){
          E[S[i] + cnt].push_back(make_pair(0, T[i] + k));
          E[T[i] + k].push_back(make_pair(0, S[i] + cnt));
        }
      }
      if (i < C - 1){
        E[S[i + 1]].push_back(make_pair(0, T[i]));
        E[T[i]].push_back(make_pair(0, S[i + 1]));
        int cnt = e[i].size();
        for (int j = 0; j < cnt - 1; j++){
          for (int k = e[i][j].first + 1; k <= e[i][j + 1].first; k++){
            E[S[i + 1] + j + 1].push_back(make_pair(0, T[i] + k));
            E[T[i] + k].push_back(make_pair(0, S[i + 1] + j + 1));
          }
        }
        for (int k = e[i][cnt - 1].first + 1; k <= y2[i].size(); k++){
          E[S[i + 1] + cnt].push_back(make_pair(0, T[i] + k));
          E[T[i] + k].push_back(make_pair(0, S[i + 1] + cnt));
        }
      }
      if (i == C - 1){
        int cnt = y2[i].size();
        for (int j = 0; j <= cnt; j++){
          E[S[i + 1]].push_back(make_pair(0, T[i] + j));
          E[T[i] + j].push_back(make_pair(0, S[i + 1]));
        }
      }
    }
    vector<int> d(T[C], -1);
    deque<pair<int, int>> dq;
    dq.push_back(make_pair(0, 0));
    while (!dq.empty()){
      int c = dq.front().first;
      int v = dq.front().second;
      dq.pop_front();
      if (d[v] == -1){
        d[v] = c;
        for (auto p : E[v]){
          int w = p.second;
          if (d[w] == -1){
            if (p.first == 0){
              dq.push_front(make_pair(c, w));
            }
            if (p.first == 1){
              dq.push_back(make_pair(c + 1, w));
            }
          }
        }
      }
    }
    int ans = 0;
    for (int i = 0; i < T[C]; i++){
      ans = max(ans, d[i]);
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 130
memory_kb: 4220
final_rank: 13

code_snippet: #define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
using namespace std;
struct point{
  double x, y;
  point(){
  }
  point(double x, double y): x(x), y(y){
  }
  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 k){
    return point(x * k, y * k);
  }
  point operator /(double k){
    return point(x / k, y / k);
  }
};
double abs(point P){
  return sqrt(P.x * P.x + P.y * P.y);
}
point rotate(point P, double t){
  return point(P.x * cos(t) - P.y * sin(t), P.x * sin(t) + P.y * cos(t));
}
double cross(point P, point Q){
  return P.x * Q.y - P.y * Q.x;
}
struct line{
  point A, B;
  line(point A, point B): A(A), B(B){
  }
};
point vec(line L){
  return L.B - L.A;
}
point line_intersection(line L1, line L2){
  return L1.A + vec(L1) * cross(L2.A - L1.A, vec(L2)) / cross(vec(L1), vec(L2));
}
int main(){
  while (true){
    int C, W;
    cin >> C >> W;
    if (C == 0 && W == 0){
      break;
    }
    vector<point> P(C);
    for (int i = 0; i < C; i++){
      cin >> P[i].x >> P[i].y;
    }
    vector<int> s(W), t(W);
    for (int i = 0; i < W; i++){
      cin >> s[i] >> t[i];
      s[i]--;
      t[i]--;
    }
    for (int i = 0; i < C; i++){
      P[i] = rotate(P[i], 0.01);
    }
    vector<double> X;
    for (int i = 0; i < C; i++){
      X.push_back(P[i].x);
    }
    sort(X.begin(), X.end());    
    for (int i = 0; i < W; i++){
      if (P[s[i]].x > P[t[i]].x){
        swap(s[i], t[i]);
      }
    }
    vector<int> l(W), r(W);
    for (int i = 0; i < W; i++){
      l[i] = lower_bound(X.begin(), X.end(), P[s[i]].x) - X.begin();
      r[i] = lower_bound(X.begin(), X.end(), P[t[i]].x) - X.begin();
    }
    vector<vector<pair<int, double>>> y(W);
    for (int i = 0; i < W; i++){
      y[i].push_back(make_pair(l[i], P[s[i]].y));
      line L(P[s[i]], P[t[i]]);
      for (int j = l[i] + 1; j < r[i]; j++){
        line L2(point(X[j], 0), point(X[j], 1));
        y[i].push_back(make_pair(j, line_intersection(L, L2).y));
      }
      y[i].push_back(make_pair(r[i], P[t[i]].y));
    }
    vector<vector<double>> y2(C);
    for (int i = 0; i < W; i++){
      int cnt = y[i].size();
      for (int j = 0; j < cnt; j++){
        int id = y[i][j].first;
        double p = y[i][j].second;
        y2[id].push_back(p);
      }
    }
    for (int i = 0; i < C; i++){
      sort(y2[i].begin(), y2[i].end());
      y2[i].erase(unique(y2[i].begin(), y2[i].end()), y2[i].end());
    }
    vector<vector<pair<int, int>>> e(C - 1);
    for (int i = 0; i < W; i++){
      vector<int> id(r[i] - l[i] + 1);
      for (int j = l[i]; j <= r[i]; j++){
        id[j - l[i]] = lower_bound(y2[j].begin(), y2[j].end(), y[i][j - l[i]].second) - y2[j].begin();
      }
      for (int j = 0; j < r[i] - l[i]; j++){
        e[l[i] + j].push_back(make_pair(id[j], id[j + 1]));
      }
    }
    for (int i = 0; i < C - 1; i++){
      sort(e[i].begin(), e[i].end());
    }
    vector<int> S(C + 2);
    S[0] = 0;
    S[1] = 1;
    for (int i = 0; i < C - 1; i++){
      S[i + 2] = S[i + 1] + e[i].size() + 1;
    }
    S[C + 1] = S[C] + 1;
    vector<int> T(C + 1);
    T[0] = S[C + 1];
    for (int i = 0; i < C; i++){
      T[i + 1] = T[i] + y2[i].size() + 1;
    }
    vector<vector<pair<int, int>>> E(T[C]);
    for (int i = 0; i <= C; i++){
      for (int j = S[i]; j < S[i + 1] - 1; j++){
        E[j].push_back(make_pair(1, j + 1));
        E[j + 1].push_back(make_pair(1, j));
      }
    }
    for (int i = 0; i < C; i++){
      if (i == 0){
        int cnt = y2[i].size();
        for (int j = 0; j <= cnt; j++){
          E[S[0]].push_back(make_pair(0, T[0] + j));
          E[T[0] + j].push_back(make_pair(0, S[0]));
        }
      }
      if (i > 0){
        E[S[i]].push_back(make_pair(0, T[i]));
        E[T[i]].push_back(make_pair(0, S[i]));
        int cnt = e[i - 1].size();
        for (int j = 0; j < cnt - 1; j++){
          if (e[i - 1][j].second != e[i - 1][j + 1].second){
            E[S[i] + j + 1].push_back(make_pair(0, T[i] + e[i - 1][j + 1].second));
            E[T[i] + e[i - 1][j + 1].second].push_back(make_pair(0, S[i] + j + 1));
          }
        }
        E[S[i] + cnt].push_back(make_pair(0, T[i] + y2[i].size()));
        E[T[i] + y2[i].size()].push_back(make_pair(0, S[i] + cnt));
      }
      if (i < C - 1){
        E[S[i + 1]].push_back(make_pair(0, T[i]));
        E[T[i]].push_back(make_pair(0, S[i + 1]));
        int cnt = e[i].size();
        for (int j = 0; j < cnt - 1; j++){
          if (e[i][j].first != e[i][j + 1].first){
            E[S[i + 1] + j + 1].push_back(make_pair(0, T[i] + e[i][j + 1].first));
            E[T[i] + e[i][j + 1].first].push_back(make_pair(0, S[i + 1] + j + 1));
          }
        }
        E[S[i + 1] + cnt].push_back(make_pair(0, T[i] + y2[i].size()));
        E[T[i] + y2[i].size()].push_back(make_pair(0, S[i + 1] + cnt));
      }
      if (i == C - 1){
        int cnt = y2[i].size();
        for (int j = 0; j <= cnt; j++){
          E[S[i + 1]].push_back(make_pair(0, T[i] + j));
          E[T[i] + j].push_back(make_pair(0, S[i + 1]));
        }
      }
    }
    vector<int> d(T[C], -1);
    deque<pair<int, int>> dq;
    dq.push_back(make_pair(0, 0));
    while (!dq.empty()){
      int c = dq.front().first;
      int v = dq.front().second;
      dq.pop_front();
      if (d[v] == -1){
        d[v] = c;
        for (auto p : E[v]){
          int w = p.second;
          if (d[w] == -1){
            if (p.first == 0){
              dq.push_front(make_pair(c, w));
            }
            if (p.first == 1){
              dq.push_back(make_pair(c + 1, w));
            }
          }
        }
      }
    }
    int ans = 0;
    for (int i = 0; i < T[C]; i++){
      ans = max(ans, d[i]);
      assert(d[i] != -1);
    }
    cout << ans << endl;
  }
}
accuracy: 0.5
time_ms: 10
memory_kb: 4032
final_rank: 17

code_snippet: #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;
}
accuracy: 1
time_ms: 20
memory_kb: 3616
final_rank: 8

code_snippet: #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;
}
accuracy: 1
time_ms: 20
memory_kb: 3592
final_rank: 6

code_snippet: #include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<math.h>
#include<complex>
#include<queue>

using namespace std;
#define rep(i,n) for(int i = 0 ; i < n ; ++i)
using ll = long long;
using ld = long double;
using Point = complex<ld>;
const ld eps = 1e-9;

ld cross(Point a,Point b){
    return imag(conj(a)*b);
}


void solve(int n,int m){
    vector<Point> p(n);
    rep(i,n){
        int x,y;
        cin>>x>>y;
        p[i]=Point(x,y);
    }
    vector<vector<int>> v(m);
    rep(i,m){
        int x,y;
        cin>>x>>y;
        --x;--y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    vector<vector<int>> used(n);
    rep(i,n){
        sort(v[i].begin(),v[i].end(),[&](int x,int y){
            return arg(p[x]-p[i])<arg(p[y]-p[i]);
        });
        used[i].resize(v[i].size());
    }
    vector<vector<int>> pols;
    rep(i,n){
        int s = v[i].size();
        rep(j,s){
            if(used[i][j])continue;
            vector<int> pol;
            pol.push_back(i);
            int cur = i;
            int nxt = v[i][j];
            used[i][j]=true;
            while(nxt!=i){
                pol.push_back(nxt);
                int idx = 0;
                while(v[nxt][idx]!=cur)++idx;
                idx = (idx+1)%v[nxt].size();
                used[nxt][idx]=true;
                cur = nxt;
                nxt = v[cur][idx];
            }
            ld sum = 0;
            rep(k,pol.size()){
                sum += cross(p[pol[k]],p[pol[(k+1)%pol.size()]]);
            }
            if(sum<0)pols.push_back(pol);
        }
    }
    int sz = pols.size();
    vector<vector<int>> vs(sz+1);
    rep(i,sz){
        int s = pols[i].size();
        rep(j,s){
            Point ext = (ld).5*(p[pols[i][(j+1)%s]]+p[pols[i][j]])
                            + Point(0,1)*eps*(p[pols[i][(j+1)%s]]-p[pols[i][j]]);
            int nxt = sz;
            rep(k,sz){
                ld sum = 0;
                rep(t,pols[k].size()){
                    sum += arg((p[pols[k][(t+1)%pols[k].size()]]-ext)/(p[pols[k][t]]-ext));
                }
                if(abs(sum)>3){
                    nxt=k;
                    break;
                }
            }
            vs[nxt].push_back(i);
            vs[i].push_back(nxt);
        }
    }
    vector<int> dist(sz+1,10000);
    dist[sz]=0;
    queue<int> q;
    q.push(sz);
    int ans = 0;
    while(q.size()){
        int cur = q.front();q.pop();
        ans = max(ans,dist[cur]);
        for(auto to : vs[cur]){
            if(dist[to]>dist[cur]+1){
                dist[to]=dist[cur]+1;
                q.push(to);
            }
        }
    }
    cout<<ans<<endl;
}



int main(){
    int n,m;
    while(cin>>n>>m,n!=0)solve(n,m);
    
}
accuracy: 1
time_ms: 190
memory_kb: 3236
final_rank: 14

code_snippet: #include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)n;i++)
#define all(c) (c).begin(),(c).end()
#define pb push_back
#define dbg(...) do{cerr<<__LINE__<<": ";dbgprint(#__VA_ARGS__, __VA_ARGS__);}while(0);

using namespace std;

namespace std{template<class S,class T>struct hash<pair<S,T>>{size_t operator()(const pair<S,T>&p)const{return ((size_t)1e9+7)*hash<S>()(p.first)+hash<T>()(p.second);}};template<class T>struct hash<vector<T>>{size_t operator()(const vector<T> &v)const{size_t h=0;for(auto i : v)h=h*((size_t)1e9+7)+hash<T>()(i)+1;return h;}};}
template<class T>ostream& operator<<(ostream &os, const vector<T> &v){os<<"[ ";rep(i,v.size())os<<v[i]<<(i==v.size()-1?" ]":", ");return os;}template<class T>ostream& operator<<(ostream &os,const set<T> &v){os<<"{ "; for(const auto &i:v)os<<i<<", ";return os<<"}";}
template<class T,class U>ostream& operator<<(ostream &os,const map<T,U> &v){os<<"{";for(const auto &i:v)os<<" "<<i.first<<": "<<i.second<<",";return os<<"}";}template<class T,class U>ostream& operator<<(ostream &os,const pair<T,U> &p){return os<<"("<<p.first<<", "<<p.second<<")";}
void dbgprint(const string &fmt){cerr<<endl;}template<class H,class... T>void dbgprint(const string &fmt,const H &h,const T&... r){cerr<<fmt.substr(0,fmt.find(","))<<"= "<<h<<" ";dbgprint(fmt.substr(fmt.find(",")+1),r...);}
typedef long long ll;typedef vector<int> vi;typedef pair<int,int> pi;
const double EPS = 1e-8, INF = 1e12, PI = acos(-1.0);
typedef complex<double> P;
namespace std{
	bool operator<(const P& a, const P& b){
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}
}
inline double cross(const P& a, const P& b){ return imag(conj(a)*b); }
inline double dot(const P& a, const P& b){ return real(conj(a)*b); }
struct L : public vector<P>{
	L(const P &a, const P &b) {
		push_back(a); push_back(b);
	}
};
typedef vector<P> G;
inline 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(norm(b)+EPS <norm(c)) return -2;      // a--b--c on line
	return 0;                                   // c is between a and b (inclusive)
}
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
double area2(const G& g) {
	double A = 0;
	for (int i = 0; i < g.size(); ++i) 
		A += cross(curr(g, i), next(g, i));
	return A;
}

int main(){
	cin.tie(0); cin.sync_with_stdio(0);
	int c, w;
	while(cin >> c >> w, c){
		G vs;
		vector<vi> v_to_es(c);
		rep(i, c){ int x, y; cin >> x >> y; vs.emplace_back(x, y); }
		rep(i, w){
			int s, t; cin >> s >> t; s--; t--;
			v_to_es[s].pb(t);
			v_to_es[t].pb(s);
		}
		rep(i, c){
			sort(all(v_to_es[i]), [&](int a, int b){
				return arg(vs[a] - vs[i]) < arg(vs[b] - vs[i]);
			});
		}
		
		int outer = -1;
		vector<vi> sur;
		set<pi> vis;
		map<pi,int> e_to_sur;
		
		function<void(int,int,vi&)> rec = [&](int prev, int cur, vi &v){
			vis.emplace(prev, cur);
			v.pb(prev);
			int k = 0;
			for(; v_to_es[cur][k] != prev; k++);
			k = (k - 1 + v_to_es[cur].size()) % v_to_es[cur].size();
			int next = v_to_es[cur][k];
			if(!vis.count(pi(cur, next))) rec(cur, next, v);
		};
		rep(i, c) for(int j : v_to_es[i]) if(!vis.count(pi(i, j))){
			vi v;
			rec(i, j, v);
			int id = sur.size();
			G g;
			rep(k, v.size()){
				e_to_sur[pi(v[k], v[(k+1) % v.size()])] = id;
				g.pb(vs[v[k]]);
			}
			if(area2(g) < 0) outer = id;
			sur.pb(v);
			//dbg(v, area2(g));
		}
		
		//dbg(outer);
		int n = sur.size();
		vector<vi> dist(n, vi(n, 10000));
		rep(i, n) dist[i][i] = 0;
		rep(i, n) rep(j, sur[i].size()){
			int k = e_to_sur[pi(sur[i][(j + 1) % sur[i].size()], sur[i][j])];
			dist[i][k] = dist[k][i] = 1;
		}
		rep(k, n) rep(i, n) rep(j, n) dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
		cout << *max_element(all(dist[outer])) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 3480
final_rank: 12

code_snippet: #include <iostream>
#include <complex>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <cstdlib>
using namespace std;

const double EPS = 1e-10;
const double INF = 1e12;
#define EQ(n,m) (abs((n)-(m)) < EPS)
#define X real()
#define Y imag()

typedef complex<double> P;
typedef vector<P> VP;
struct L : VP{
    L(const P& a, const P& b){ resize(2); at(0)=a; at(1)=b; }
    L(){ resize(2); }
};

namespace std{
    bool operator < (const P &a, const P &b){
        return !EQ(a.X, b.X)? a.X<b.X : a.Y<b.Y;
    }
    bool operator == (const P &a, const P &b){
        return abs(a-b) < EPS;
    }
}

double dot(P a, P b){
    return (conj(a)*b).X;
}
double cross(P a, P b){
    return (conj(a)*b).Y;
}
int ccw(P a, P b, P c){
    b -= a;
    c -= a;
    if(cross(b,c) > EPS) return +1; //ccw
    if(cross(b,c) <-EPS) return -1; //cw
    if(dot(b,c) < EPS) return +2; //c-a-b
    if(norm(b) < norm(c)) return -2; //a-b-c
    return 0; //a-c-b
}

P projection(const L& l, const P& p) {
  double t = dot(p-l[0], l[0]-l[1]) / norm(l[0]-l[1]);
  return l[0] + t*(l[0]-l[1]);
}

P crosspointLL(const L &l, const L &m) {
  double A = cross(l[1]-l[0], m[1]-m[0]);
  double B = cross(l[1]-l[0], l[1]-m[0]);
  return m[0] + B /A *(m[1]-m[0]);
}

double getangle(const P &p, const P &a, const P &b){ //clockwise
    P proj = projection(L(p,a), b);
    int minus = (dot(a-p, b-p)>=0)? 1 :-1;
    if(ccw(p,a,b)!=1){
        return atan2(abs(b-proj), minus*abs(p-proj));
    }else{
        return 2*M_PI - atan2(abs(b-proj), minus*abs(p-proj));
    }
}
double getarea(const VP &p) {
	double ret = 0;
	for (int i=0; i<(int)p.size(); i++){ 
		ret += cross(p[i], p[(i+1)%p.size()]);
	}
	return ret*0.5;
}

int leftmostpoint(int &pidx, int &cidx, vector<int> &vec, VP &plist){
	P prev = plist[pidx];
	P curr = plist[cidx];
	int nextidx = -1;
	double minangle = INF;
	for(int i=0; i<(int)vec.size(); i++){
		if(vec[i]==pidx) continue;
		double angle = getangle(curr, prev, plist[vec[i]]);
		if(angle < minangle){
			minangle = angle;
			nextidx = i;
		}
	}
	pidx = cidx;
	cidx = vec[nextidx];
	return nextidx;
}

vector<vector<int> > makeDualGraph(vector<vector<int> > &adj, VP &plist, int &out){
    map<pair<int,int>, int> edgelist;
    vector<vector<int> > poly;
    vector<vector<bool> > used(adj.size());
    for(int i=0; i<(int)adj.size(); i++){
        used[i] = vector<bool>(adj[i].size(), false);
    }
    
    int numarea=0;
    for(int i=0; i<(int)adj.size(); i++){
    	for(int j=0; j<(int)adj[i].size(); j++){
    		if(used[i][j]) continue;
    		used[i][j] = true;
    		numarea++;
    		vector<int> border;
    		VP vlist;
    		border.push_back(i);
    		vlist.push_back(plist[i]);
    		int prev = i;
    		int curr = adj[i][j];
    		while(curr!=i){
    			border.push_back(curr);
    			vlist.push_back(plist[curr]);
    			int idx = leftmostpoint(prev, curr, adj[curr], plist);
    			used[prev][idx] = true;
    		}
    		poly.push_back(border);
    		if(getarea(vlist) < 0) out = numarea-1;
    	}
    }
    
    vector<vector<int> > dual(numarea);
    for(int i=0; i<numarea; i++){
    	for(int j=0; j<(int)poly[i].size(); j++){
    		int a = poly[i][j];
    		int b = poly[i][(j+1)%(int)poly[i].size()];
    		pair<int,int> key = make_pair(min(a,b), max(a,b));
    		if(edgelist.count(key) == 0){
    			edgelist[key] = i;
    		}else{
    			dual[i].push_back(edgelist[key]);
    			dual[edgelist[key]].push_back(i);
    		}
    	}
    }
    
    for(int i=0; i<(int)dual.size(); i++){
        sort(dual[i].begin(), dual[i].end());
        dual[i].erase(unique(dual[i].begin(), dual[i].end()), dual[i].end());
    }
    return dual;
}

int main(){
	while(1){
		int c,w;
		cin >> c >> w;
		if(c==0) break;
		
		VP bar(c);
		for(int i=0; i<c; i++){
			int x,y;
			cin >> x >> y;
			bar[i] = P(x,y);
		}
		
		vector<vector<int> > adj(c);
		for(int i=0; i<w; i++){
			int s,t;
			cin >> s >> t;
			s--; t--;
			adj[s].push_back(t);
			adj[t].push_back(s);
		}
		int out;
		vector<vector<int> > dual = makeDualGraph(adj, bar, out);
		
		int numarea = dual.size();
		set<int> reach;
		reach.insert(out);
		int ans = 0;
		while(1){
			if((int)reach.size() == numarea) break;
			set<int> newreach;
			for(set<int>::iterator itr=reach.begin(); itr!=reach.end(); itr++){
				newreach.insert(*itr);
				for(int i=0; i<(int)dual[*itr].size(); i++){
					newreach.insert(dual[*itr][i]);
				}
			}
			reach = newreach;
			ans++;
		}
		cout << ans << endl;
	}
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3352
final_rank: 1

code_snippet: #include <bits/stdc++.h>

#define REP(i,n) for(int i=0;i<(int)(n);i++)
#define ALL(x) (x).begin(),(x).end()

using namespace std;

typedef long long ll;
typedef long double ld;
typedef complex<ld> Point;
const ld INF = 1e10;
const ld eps = 1e-9, pi = acos(-1.0);

namespace std {
  bool operator<(const Point &lhs, const Point &rhs) {
    if (lhs.real() < rhs.real() - eps) return true;
    if (lhs.real() > rhs.real() + eps) return false;
    return lhs.imag() < rhs.imag();
  }
}

Point input_point() {
  ld x, y;
  cin >> x >> y;
  return Point(x, y);
}

bool eq(ld a, ld b) {
  return (abs(a - b) < eps);
}

ld dot(Point a, Point b) {
  return real(conj(a) * b);
}

ld cross(Point a, Point b) {
  return imag(conj(a) * b);
}

class Line {
public:
  Point a, b;
  Line () : a(Point(0, 0)), b(Point(0, 0)) {}
  Line (Point a, Point b) : a(a), b(b) {}
};

class Circle {
public:
  Point p;
  ld r;
  Circle () : p(Point(0, 0)), r(0) {}
  Circle (Point p, ld r) : p(p), r(r) {}
};

int ccw (Point a, Point b, Point c) {
  b -= a; c -= a;
  if (cross(b, c) > eps) return 1;
  if (cross(b, c) < -eps) return -1;
  if (dot(b, c) < 0) return 2;
  if (norm(b) < norm(c)) return -2;
  return 0;
}

bool isis_ll (Line l, Line m) {
  return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

bool isis_ls (Line l, Line s) {
  return isis_ll(l, s) &&
    (cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

bool isis_ss(Line s, Line t) {
  return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
    ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

bool isis_lp (Line l, Point p) {
  return (abs(cross(l.b - p, l.a - p)) < eps);
}

bool isis_sp (Line s, Point p) {
  return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

Point proj (Line l, Point p) {
  ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
  return l.a + t * (l.a - l.b);
}

Point is_ll (Line s, Line t) {
  Point sv = s.b - s.a, tv = t.b - t.a;
  assert(cross(sv, tv) != 0);
  return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

ld dist_lp (Line l, Point p) {
  return abs(p - proj(l, p));
}

ld dist_ll (Line l, Line m) {
  return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

ld dist_ls (Line l, Line s) {
  return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

ld dist_sp (Line s, Point p) {
  Point r = proj(s, p);
  return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

ld dist_ss (Line s, Line t) {
  if (isis_ss(s, t)) return 0;
  return min({dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b)});
}

vector<Point> is_cc (Circle c1, Circle c2){
  vector<Point> res;
  ld d = abs(c1.p - c2.p);
  ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
  ld dfr = c1.r * c1.r - rc * rc;
  if (abs(dfr) < eps) dfr = 0.0;
  else if (dfr < 0.0) return res;
  ld rs = sqrt(dfr);
  Point diff = (c2.p - c1.p) / d;
  res.push_back(c1.p + diff * Point(rc, rs));
  if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
  return res;
}

vector<Point> is_lc (Circle c, Line l){
  vector<Point> res;
  ld d = dist_lp(l, c.p);
  if (d < c.r + eps){
    ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d);
    Point nor = (l.a - l.b) / abs(l.a - l.b);
    res.push_back(proj(l, c.p) + len * nor);
    res.push_back(proj(l, c.p) - len * nor);
  }
  return res;
}

vector<Point> is_sc(Circle c, Line l){
  vector<Point> v = is_lc(c, l), res;
  for (Point p : v)
    if (isis_sp(l, p)) res.push_back(p);
  return res;
}

vector<Line> tangent_cp(Circle c, Point p) {
  vector<Line> ret;
  Point v = c.p - p;
  ld d = abs(v);
  ld l = sqrt(norm(v) - c.r * c.r);
  if (isnan(l)) { return ret; }
  Point v1 = v * Point(l / d,  c.r / d);
  Point v2 = v * Point(l / d, -c.r / d);
  ret.push_back(Line(p, p + v1));
  if (l < eps) return ret;
  ret.push_back(Line(p, p + v2));
  return ret;
}

vector<Line> tangent_cc(Circle c1, Circle c2) {
  vector<Line> ret;
  if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
    Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
    ret = tangent_cp(c1, center);
  }
  if (abs(c1.r - c2.r) > eps) {
    Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
    vector<Line> nret = tangent_cp(c1, out);
    ret.insert(ret.end(), ALL(nret));
  }
  else {
    Point v = c2.p - c1.p;
    v /= abs(v);
    Point q1 = c1.p + v * Point(0,  1) * c1.r;
    Point q2 = c1.p + v * Point(0, -1) * c1.r;
    ret.push_back(Line(q1, q1 + v));
    ret.push_back(Line(q2, q2 + v));
  }
  return ret;
}

typedef vector<Point> Polygon;

ld area(const Polygon &p) {
  ld res = 0;
  int n = p.size();
  REP(j,n) res += cross(p[j], p[(j+1)%n]);
  return res / 2;
}

bool is_counter_clockwise (const Polygon &poly) {
  ld angle = 0;
  int n = poly.size();
  REP(i,n) {
    Point a = poly[i], b = poly[(i+1)%n], c = poly[(i+2)%n];
    angle += arg((c - b) / (b - a));
  }
  return angle > eps;
}

int is_in_polygon (const Polygon &poly, Point p) {
  ld angle = 0;
  int n = poly.size();
  REP(i,n) {
    Point a = poly[i], b = poly[(i+1)%n];
    if (isis_sp(Line(a, b), p)) return 1;
    angle += arg((b - p) / (a - p));
  }
  return eq(angle, 0) ? 0 : 2;
}

Polygon convex_hull(vector<Point> ps) {
  int n = ps.size();
  int k = 0;
  sort(ps.begin(), ps.end());
  Polygon ch(2 * n);
  for (int i = 0; i < n; ch[k++] = ps[i++])
    while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
  for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
    while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
  ch.resize(k - 1);
  return ch;
}

Polygon convex_cut(const Polygon &ps, Line l) {
  int n = ps.size();
  Polygon Q;
  REP(i,n) {
    Point A = ps[i], B = ps[(i+1)%n];
    Line m = Line(A, B);
    if (ccw(l.a, l.b, A) != -1) Q.push_back(A);
    if (ccw(l.a, l.b, A) * ccw(l.a, l.b, B) < 0 && isis_ll(l, m))
      Q.push_back(is_ll(l, m));
  }
  return Q;
}

void add_point(vector<Point> &ps, Point p) {
  for (Point q : ps) if (abs(q - p) < eps) return;
  ps.push_back(p);
}

typedef ll Weight;

struct Edge { int from, to; Weight weight;
  Edge(int from, int to, Weight weight) :
    from(from), to(to), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.from != f.from ? e.from < f.from : e.to < f.to;
}

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

void add_edge(Graph &g, int from, int to, Weight weight) {
  g[from].push_back((Edge){from, to, weight});
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
  int n = p.size(), m = s.size();
  Graph g(n);
  REP(i,m) {
    vector<pair<ld,int>> vec;
    REP(j,n) if (isis_sp(s[i], p[j]))
      vec.emplace_back(abs(s[i].a - p[j]), j);
    sort(ALL(vec));
    REP(j,vec.size()-1) {
      int from = vec[j].second, to = vec[j+1].second;
      add_edge(g, from, to, abs(p[from] - p[to]));
    }
  }
  return g;
}

Graph circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
  int n = p.size(), m = c.size();
  Graph g(n);
  REP(i,m) {
    vector<pair<ld,int>> vec;
    REP(j,n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
      vec.emplace_back(arg(c[i].p - p[j]), j);
    sort(ALL(vec));
    REP(j,vec.size()-1) {
      int from = vec[j].second, to = vec[j+1].second;
      ld angle = vec[j+1].first - vec[j].first;
      add_edge(g, from, to, angle * c[i].r);
    }
    if (vec.size() >= 2) {
      int from = vec.back().second, to = vec.front().first;
      ld angle = vec.front().first - vec.back().first;
      add_edge(g, from, to, angle * c[i].r);
    }
  }
  return g;
}

vector<vector<int>> polygon;
vector<int> seg2p[1024][1024];

Graph dual_graph(const vector<Line> &s, const vector<Point> &p) {
  int N = p.size();
  polygon.clear();
  REP(i,1024) REP(j,1024) seg2p[i][j].clear();
  vector<vector<tuple<ld,int,bool>>> tup(N);
  REP(i,s.size()) {
    int a = -1, b = -1;
    REP(j,N) if (abs(s[i].a - p[j]) < eps) a = j;
    REP(j,N) if (abs(s[i].b - p[j]) < eps) b = j;
    assert(a >= 0 && b >= 0);
    tup[a].emplace_back(arg(s[i].b - s[i].a), b, false);
    tup[b].emplace_back(arg(s[i].a - s[i].b), a, false);
  }
  REP(i,N) sort(ALL(tup[i]));
  REP(i,N) {
    REP(j,tup[i].size()) {
      ld angle; int pos = j, from = i, to; bool flag;
      tie(angle, to, flag) = tup[i][j];
      if (flag) continue;
      vector<int> ps;
      while (!flag) {
        ps.push_back(from);
        get<2>(tup[from][pos]) = true;
        seg2p[from][to].push_back(polygon.size());
        seg2p[to][from].push_back(polygon.size());
        angle += pi + eps;
        if (angle > pi) angle -= 2 * pi;
        auto it = lower_bound(ALL(tup[to]), make_tuple(angle, 0, false));
        if (it == tup[to].end()) it = tup[to].begin();
        from = to; tie(angle, to, flag) = *it;
        pos = it - tup[from].begin();
      }
      polygon.push_back(ps);
    }
  }
  for(int i=0;i<polygon.size();i++){
    Polygon ps;
    for(int j=0; j<polygon[i].size(); j++)
      ps.push_back(p[polygon[i][j]]);
    bool soto = true;
    for(int i=0;i<p.size();i++){
      if(is_in_polygon(ps, p[i]) == 0)
	soto=false;
    }
    if(soto){
      vector<int> hoge = polygon[0];
      vector<int> huga = polygon[i];
      polygon[0] = huga;
      polygon[i] = hoge;
      //cout << "kore" << i << endl;
      break;
    }
  }
  /*cout << endl;
  for(int i=0;i<polygon.size();i++){
    for(int j=0;j<polygon[i].size();j++)
      cout << polygon[i][j] << " ";
    cout << endl;
    }*/
    
  Graph g(polygon.size());
  REP(i,N) REP(j,i) {
    if (seg2p[i][j].size() == 2) {
      int from = seg2p[i][j][0], to = seg2p[i][j][1];
      g[from].push_back(Edge(from, to, 1));
      g[to].push_back(Edge(to, from, 1));
    }
  }
  return g;
}

const ld zoom = 25;
const ld centerX = 6;
const ld centerY = 5;

void change_color(int r, int g, int b) {
  fprintf(stderr, "c.strokeStyle = 'rgb(%d, %d, %d)';\n", r, g, b);
}

int cordx(Point p) { return 400 + zoom * (p.real() - centerX); }
int cordy(Point p) { return 400 - zoom * (p.imag() - centerY); }

#define cord(p) cordx(p),cordy(p)

void draw_point(Point p) {
  fprintf(stderr, "circle(%d, %d, %d)\n", cord(p), 2);
}

void draw_segment(Line l) {
  fprintf(stderr, "line(%d, %d, %d, %d)\n", cord(l.a), cord(l.b));
}

void draw_line(Line l) {
  Point v = l.b - l.a;
  Line m(l.a - v * Point(1e4, 0), l.b + v * Point(1e4, 0));
  fprintf(stderr, "line(%d, %d, %d, %d)\n", cord(m.a), cord(m.b));
}

void draw_polygon(const Polygon &p) {
  int n = p.size();
  REP(i,n) draw_segment(Line(p[i], p[(i+1)%n]));
}

void draw_circle(Circle c) {
  fprintf(stderr, "circle(%d, %d, %d)\n", cord(c.p), (int)(zoom * c.r));
}

void shortestPath(const Graph &g, int s,
		  vector<Weight> &dist, vector<int> &prev) {
  int n = g.size();
  dist.assign(n, INF); dist[s] = 0;
  prev.assign(n, -1);
  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 (prev[e.to] != -1) continue;
    prev[e.to] = e.from;
    for(auto f=g[e.to].begin();f!=g[e.to].end();f++) {
      if (dist[f->to] > e.weight+f->weight) {
        dist[f->to] = e.weight+f->weight;
        Q.push(Edge(f->from, f->to, e.weight+f->weight));
      }
    }
  }
}

int main(){
  ll C, W;
  while(cin >> C >> W, C!=0 || W!=0){
    vector<Point> v;
    for(int i=0;i<C;i++)
      v.push_back(input_point());
    vector<Line> e;
    for(int i=0;i<W;i++){
      ll s,t;
      cin >> s >> t;
      s--; t--;
      e.push_back(Line(v[s], v[t]));
    }
    Graph g = dual_graph(e, v);
    vector<Weight> dist;
    vector<int> prev;
    shortestPath(g, 0, dist, prev);
    ll ans = 0;
    for(int i=0;i<dist.size();i++)
      ans = max(ans, dist[i]);
    cout << ans << endl;
  }
  return 0;
}
accuracy: 0.125
time_ms: 20
memory_kb: 27900
final_rank: 19

code_snippet: #include "bits/stdc++.h"

#define REP(i,n) for(ll i=0;i<ll(n);++i)
#define RREP(i,n) for(ll i=ll(n)-1;i>=0;--i)
#define FOR(i,m,n) for(ll i=m;i<ll(n);++i)
#define RFOR(i,m,n) for(ll i=ll(n)-1;i>=ll(m);--i)
#define ALL(v) (v).begin(),(v).end()
#define UNIQUE(v) v.erase(unique(ALL(v)),v.end());
#define DUMP(v) REP(aa, (v).size()) { cout << v[aa]; if (aa != v.size() - 1)cout << " "; else cout << endl; }
#define INF 1000000001ll
#define MOD 1000000007ll
#define EPS 1e-9

const int dx[8] = { 1,1,0,-1,-1,-1,0,1 };
const int dy[8] = { 0,1,1,1,0,-1,-1,-1 };


using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
ll max(ll a, int b) { return max(a, ll(b)); }
ll max(int a, ll b) { return max(ll(a), b); }
ll min(ll a, int b) { return min(a, ll(b)); }
ll min(int a, ll b) { return min(ll(a), b); }
///(´・ω・`)(´・ω・`)(´・ω・`)(´・ω・`)(´・ω・`)(´・ω・`)///


using namespace std;

typedef long double ld;
typedef complex<ld> Point;

const ld eps = 1e-9, pi = acos(-1.0);

namespace std {
	bool operator<(const Point &lhs, const Point &rhs) {
		if (lhs.real() < rhs.real() - eps) return true;
		if (lhs.real() > rhs.real() + eps) return false;
		return lhs.imag() < rhs.imag();
	}
}

Point input_point() {
	ld x, y;
	cin >> x >> y;
	return Point(x, y);
}

bool eq(ld a, ld b) {
	return (abs(a - b) < eps);
}

ld dot(Point a, Point b) {
	return real(conj(a) * b);
}

ld cross(Point a, Point b) {
	return imag(conj(a) * b);
}

class Line {
public:
	Point a, b;
	Line() : a(Point(0, 0)), b(Point(0, 0)) {}
	Line(Point a, Point b) : a(a), b(b) {}
};

class Circle {
public:
	Point p;
	ld r;
	Circle() : p(Point(0, 0)), r(0) {}
	Circle(Point p, ld r) : p(p), r(r) {}
};

int ccw(Point a, Point b, Point c) {
	b -= a; c -= a;
	if (cross(b, c) > eps) return 1;
	if (cross(b, c) < -eps) return -1;
	if (dot(b, c) < 0) return 2;
	if (norm(b) < norm(c)) return -2;
	return 0;
}

bool isis_ll(Line l, Line m) {
	return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

bool isis_ls(Line l, Line s) {
	return isis_ll(l, s) &&
		(cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

bool isis_ss(Line s, Line t) {
	return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
		ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

bool isis_lp(Line l, Point p) {
	return (abs(cross(l.b - p, l.a - p)) < eps);
}

bool isis_sp(Line s, Point p) {
	return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

Point proj(Line l, Point p) {
	ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
	return l.a + t * (l.a - l.b);
}

Point is_ll(Line s, Line t) {
	Point sv = s.b - s.a, tv = t.b - t.a;
	assert(cross(sv, tv) != 0);
	return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

ld dist_lp(Line l, Point p) {
	return abs(p - proj(l, p));
}

ld dist_ll(Line l, Line m) {
	return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

ld dist_ls(Line l, Line s) {
	return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

ld dist_sp(Line s, Point p) {
	Point r = proj(s, p);
	return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

ld dist_ss(Line s, Line t) {
	if (isis_ss(s, t)) return 0;
	return min({ dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b) });
}

vector<Point> is_cc(Circle c1, Circle c2) {
	vector<Point> res;
	ld d = abs(c1.p - c2.p);
	ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
	ld dfr = c1.r * c1.r - rc * rc;
	if (abs(dfr) < eps) dfr = 0.0;
	else if (dfr < 0.0) return res;
	ld rs = sqrt(dfr);
	Point diff = (c2.p - c1.p) / d;
	res.push_back(c1.p + diff * Point(rc, rs));
	if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
	return res;
}

vector<Point> is_lc(Circle c, Line l) {
	vector<Point> res;
	ld d = dist_lp(l, c.p);
	if (d < c.r + eps) {
		ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d);
		Point nor = (l.a - l.b) / abs(l.a - l.b);
		res.push_back(proj(l, c.p) + len * nor);
		res.push_back(proj(l, c.p) - len * nor);
	}
	return res;
}

vector<Point> is_sc(Circle c, Line l) {
	vector<Point> v = is_lc(c, l), res;
	for (Point p : v)
		if (isis_sp(l, p)) res.push_back(p);
	return res;
}

vector<Line> tangent_cp(Circle c, Point p) {
	vector<Line> ret;
	Point v = c.p - p;
	ld d = abs(v);
	ld l = sqrt(norm(v) - c.r * c.r);
	if (isnan(l)) { return ret; }
	Point v1 = v * Point(l / d, c.r / d);
	Point v2 = v * Point(l / d, -c.r / d);
	ret.push_back(Line(p, p + v1));
	if (l < eps) return ret;
	ret.push_back(Line(p, p + v2));
	return ret;
}

vector<Line> tangent_cc(Circle c1, Circle c2) {
	vector<Line> ret;
	if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
		Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
		ret = tangent_cp(c1, center);
	}
	if (abs(c1.r - c2.r) > eps) {
		Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
		vector<Line> nret = tangent_cp(c1, out);
		ret.insert(ret.end(), ALL(nret));
	}
	else {
		Point v = c2.p - c1.p;
		v /= abs(v);
		Point q1 = c1.p + v * Point(0, 1) * c1.r;
		Point q2 = c1.p + v * Point(0, -1) * c1.r;
		ret.push_back(Line(q1, q1 + v));
		ret.push_back(Line(q2, q2 + v));
	}
	return ret;
}

typedef vector<Point> Polygon;

ld area(const Polygon &p) {
	ld res = 0;
	int n = p.size();
	REP(j, n) res += cross(p[j], p[(j + 1) % n]);
	return res / 2;
}

bool is_counter_clockwise(const Polygon &poly) {
	ld angle = 0;
	int n = poly.size();
	REP(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n], c = poly[(i + 2) % n];
		angle += arg((c - b) / (b - a));
	}
	return angle > eps;
}

int is_in_polygon(const Polygon &poly, Point p) {
	ld angle = 0;
	int n = poly.size();
	REP(i, n) {
		Point a = poly[i], b = poly[(i + 1) % n];
		if (isis_sp(Line(a, b), p)) return 1;
		angle += arg((b - p) / (a - p));
	}
	return eq(angle, 0) ? 0 : 2;
}

Polygon convex_hull(vector<Point> ps) {
	int n = ps.size();
	int k = 0;
	sort(ps.begin(), ps.end());
	Polygon ch(2 * n);
	for (int i = 0; i < n; ch[k++] = ps[i++])
		while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
		while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
	ch.resize(k - 1);
	return ch;
}

Polygon convex_cut(const Polygon &ps, Line l) {
	int n = ps.size();
	Polygon Q;
	REP(i, n) {
		Point A = ps[i], B = ps[(i + 1) % n];
		Line m = Line(A, B);
		if (ccw(l.a, l.b, A) != -1) Q.push_back(A);
		if (ccw(l.a, l.b, A) * ccw(l.a, l.b, B) < 0 && isis_ll(l, m))
			Q.push_back(is_ll(l, m));
	}
	return Q;
}

void add_point(vector<Point> &ps, Point p) {
	for (Point q : ps) if (abs(q - p) < eps) return;
	ps.push_back(p);
}

typedef int Weight;

struct Edge { int from, to; Weight weight; };

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

void add_edge(Graph &g, int from, int to, Weight weight) {
	g[from].push_back(Edge { from, to, weight });
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
	int n = p.size(), m = s.size();
	Graph g(n);
	REP(i, m) {
		vector<pair<ld, int>> vec;
		REP(j, n) if (isis_sp(s[i], p[j]))
			vec.emplace_back(abs(s[i].a - p[j]), j);
		sort(ALL(vec));
		REP(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			add_edge(g, from, to, abs(p[from] - p[to]));
		}
	}
	return g;
}

Graph circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
	int n = p.size(), m = c.size();
	Graph g(n);
	REP(i, m) {
		vector<pair<ld, int>> vec;
		REP(j, n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
			vec.emplace_back(arg(c[i].p - p[j]), j);
		sort(ALL(vec));
		REP(j, vec.size() - 1) {
			int from = vec[j].second, to = vec[j + 1].second;
			ld angle = vec[j + 1].first - vec[j].first;
			add_edge(g, from, to, angle * c[i].r);
		}
		if (vec.size() >= 2) {
			int from = vec.back().second, to = vec.front().first;
			ld angle = vec.front().first - vec.back().first;
			add_edge(g, from, to, angle * c[i].r);
		}
	}
	return g;
}

vector<vector<int>> polygon;
vector<int> seg2p[1024][1024];

Graph dual_graph(const vector<Line> &s, const vector<Point> &p) {
	int N = p.size();
	polygon.clear();
	REP(i, 1024) REP(j, 1024) seg2p[i][j].clear();
	vector<vector<tuple<ld, int, bool>>> tup(N);
	REP(i, s.size()) {
		int a = -1, b = -1;
		REP(j, N) if (abs(s[i].a - p[j]) < eps) a = j;
		REP(j, N) if (abs(s[i].b - p[j]) < eps) b = j;
		assert(a >= 0 && b >= 0);
		tup[a].emplace_back(arg(s[i].b - s[i].a), b, false);
		tup[b].emplace_back(arg(s[i].a - s[i].b), a, false);
	}
	REP(i, N) sort(ALL(tup[i]));
	REP(i, N) {
		REP(j, tup[i].size()) {
			ld angle; int pos = j, from = i, to; bool flag;
			tie(angle, to, flag) = tup[i][j];
			if (flag) continue;
			vector<int> ps;
			while (!flag) {
				ps.push_back(from);
				get<2>(tup[from][pos]) = true;
				seg2p[from][to].push_back(polygon.size());
				seg2p[to][from].push_back(polygon.size());
				angle += pi + eps;
				if (angle > pi) angle -= 2 * pi;
				auto it = lower_bound(ALL(tup[to]), make_tuple(angle, 0, false));
				if (it == tup[to].end()) it = tup[to].begin();
				from = to; tie(angle, to, flag) = *it;
				pos = it - tup[from].begin();
			}
			polygon.push_back(ps);
		}
	}
	Graph g(polygon.size());
	REP(i, N) REP(j, i) {
		if (seg2p[i][j].size() == 2) {
			int from = seg2p[i][j][0], to = seg2p[i][j][1];
			g[from].push_back(Edge{ from, to });
			g[to].push_back(Edge{ to, from });
		}
	}
	return g;
}

const ld zoom = 25;
const ld centerX = 6;
const ld centerY = 5;

void change_color(int r, int g, int b) {
	fprintf(stderr, "c.strokeStyle = 'rgb(%d, %d, %d)';\n", r, g, b);
}

int cordx(Point p) { return 400 + zoom * (p.real() - centerX); }
int cordy(Point p) { return 400 - zoom * (p.imag() - centerY); }

#define cord(p) cordx(p),cordy(p)

void draw_point(Point p) {
	fprintf(stderr, "circle(%d, %d, %d)\n", cord(p), 2);
}

void draw_segment(Line l) {
	fprintf(stderr, "line(%d, %d, %d, %d)\n", cord(l.a), cord(l.b));
}

void draw_line(Line l) {
	Point v = l.b - l.a;
	Line m(l.a - v * Point(1e4, 0), l.b + v * Point(1e4, 0));
	fprintf(stderr, "line(%d, %d, %d, %d)\n", cord(m.a), cord(m.b));
}

void draw_polygon(const Polygon &p) {
	int n = p.size();
	REP(i, n) draw_segment(Line(p[i], p[(i + 1) % n]));
}

void draw_circle(Circle c) {
	fprintf(stderr, "circle(%d, %d, %d)\n", cord(c.p), (int)(zoom * c.r));
}

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);
	int c, w;
	while (cin >> c >> w, c) {
		vector<Point> p(c);
		REP(i, c) {
			int x, y;
			cin >> x >> y;
			p[i]=Point( x,y );
		}
		vector<Line> l(w);
		REP(i, w) {
			int s, t;
			cin >> s >> t;
			s--; t--;
			l[i] =Line( p[s],p[t] );
		}
		Graph g = dual_graph(l, p);
		int n = g.size();
		vvi d(n, vi(n, INF));
		REP(i, n) {
			REP(j, g[i].size()) {
				int from = g[i][j].from, to = g[i][j].to;
				d[from][to] = 1;
				d[to][from] = 1;
			}
		}
		REP(i, n)d[i][i] = 0;
		REP(k, n) {
			REP(i, n) {
				REP(j, n) {
					d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
				}
			}
		}
		int ans = -INF;
		REP(i, n) {
			REP(j, n) {
				ans = max(ans, d[i][j]);
			}
		}
		assert(ans != INF);
		cout << ans << endl;
	}
	
}
accuracy: 0.125
time_ms: 20
memory_kb: 27804
final_rank: 18

code_snippet: #include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<ll, ll> P;

#define each(i,a) for (auto&& i : a)
#define FOR(i,a,b) for (ll i=(a),__last_##i=(b);i<__last_##i;i++)
#define RFOR(i,a,b) for (ll i=(b)-1,__last_##i=(a);i>=__last_##i;i--)
#define REP(i,n) FOR(i,0,n)
#define RREP(i,n) RFOR(i,0,n)
#define __GET_MACRO3(_1, _2, _3, NAME, ...) NAME
#define rep(...) __GET_MACRO3(__VA_ARGS__, FOR, REP)(__VA_ARGS__)
#define rrep(...) __GET_MACRO3(__VA_ARGS__, RFOR, RREP)(__VA_ARGS__)
#define pb push_back
#define all(a) (a).begin(),(a).end()
#define chmin(x,v) x = min(x, v)
#define chmax(x,v) x = max(x, v)

const ll linf = 1e18;
const int inf = 1e9;
const double eps = 1e-12;
const double pi = acos(-1);

template<typename T>
istream& operator>>(istream& is, vector<T>& vec) {
    each(x,vec) is >> x;
    return is;
}
template<typename T>
ostream& operator<<(ostream& os, const vector<T>& vec) {
    rep(i,vec.size()) {
        if (i) os << " ";
        os << vec[i];
    }
    return os;
}
template<typename T>
ostream& operator<<(ostream& os, const vector< vector<T> >& vec) {
    rep(i,vec.size()) {
        if (i) os << endl;
        os << vec[i];
    }
    return os;
}
using ld = double;
using Point = complex<ld>;
namespace std {
    bool operator<(const Point &lhs, const Point &rhs) {
        if (lhs.real() < rhs.real() - eps) return true;
        if (lhs.real() > rhs.real() + eps) return false;
        return lhs.imag() < rhs.imag();
    }
}

Point input_point() {
    ld x, y;
    cin >> x >> y;
    return Point(x, y);
}

bool eq(ld a, ld b) {
    return (abs(a - b) < eps);
}

ld dot(Point a, Point b) {
    return real(conj(a) * b);
}

ld cross(Point a, Point b) {
    return imag(conj(a) * b);
}

class Line {
public:
    Point a, b;
    Line () : a(Point(0, 0)), b(Point(0, 0)) {}
    Line (Point a, Point b) : a(a), b(b) {}
};

class Circle {
public:
    Point p;
    ld r;
    Circle () : p(Point(0, 0)), r(0) {}
    Circle (Point p, ld r) : p(p), r(r) {}
};

int ccw (Point a, Point b, Point c) {
    b -= a; c -= a;
    if (cross(b, c) > eps) return 1;
    if (cross(b, c) < -eps) return -1;
    if (dot(b, c) < 0) return 2;
    if (norm(b) < norm(c)) return -2;
    return 0;
}

bool isis_ll (Line l, Line m) {
    return !eq(cross(l.b - l.a, m.b - m.a), 0);
}

bool isis_ls (Line l, Line s) {
    return isis_ll(l, s) &&
        (cross(l.b - l.a, s.a - l.a) * cross(l.b - l.a, s.b - l.a) < eps);
}

bool isis_ss(Line s, Line t) {
    return ccw(s.a, s.b, t.a) * ccw(s.a, s.b, t.b) <= 0 &&
        ccw(t.a, t.b, s.a) * ccw(t.a, t.b, s.b) <= 0;
}

bool isis_lp (Line l, Point p) {
    return (abs(cross(l.b - p, l.a - p)) < eps);
}

bool isis_sp (Line s, Point p) {
    return (abs(s.a - p) + abs(s.b - p) - abs(s.b - s.a) < eps);
}

Point proj (Line l, Point p) {
    ld t = dot(p - l.a, l.a - l.b) / norm(l.a - l.b);
    return l.a + t * (l.a - l.b);
}

Point is_ll (Line s, Line t) {
    Point sv = s.b - s.a, tv = t.b - t.a;
    assert(cross(sv, tv) != 0);
    return s.a + sv * cross(tv, t.a - s.a) / cross(tv, sv);
}

ld dist_lp (Line l, Point p) {
    return abs(p - proj(l, p));
}

ld dist_ll (Line l, Line m) {
    return isis_ll(l, m) ? 0 : dist_lp(l, m.a);
}

ld dist_ls (Line l, Line s) {
    return isis_ls(l, s) ? 0 : min(dist_lp(l, s.a), dist_lp(l, s.b));
}

ld dist_sp (Line s, Point p) {
    Point r = proj(s, p);
    return isis_sp(s, r) ? abs(r - p) : min(abs(s.a - p), abs(s.b - p));
}

ld dist_ss (Line s, Line t) {
    if (isis_ss(s, t)) return 0;
    return min({dist_sp(s, t.a), dist_sp(s, t.b), dist_sp(t, s.a), dist_sp(t, s.b)});
}

vector<Point> is_cc (Circle c1, Circle c2){
    vector<Point> res;
    ld d = abs(c1.p - c2.p);
    ld rc = (d * d + c1.r * c1.r - c2.r * c2.r) / (2 * d);
    ld dfr = c1.r * c1.r - rc * rc;
    if (abs(dfr) < eps) dfr = 0.0;
    else if (dfr < 0.0) return res;
    ld rs = sqrt(dfr);
    Point diff = (c2.p - c1.p) / d;
    res.push_back(c1.p + diff * Point(rc, rs));
    if (dfr != 0.0) res.push_back(c1.p + diff * Point(rc, -rs));
    return res;
}

vector<Point> is_lc (Circle c, Line l){
    vector<Point> res;
    ld d = dist_lp(l, c.p);
    if (d < c.r + eps){
        ld len = (d > c.r) ? 0.0 : sqrt(c.r * c.r - d * d);
        Point nor = (l.a - l.b) / abs(l.a - l.b);
        res.push_back(proj(l, c.p) + len * nor);
        res.push_back(proj(l, c.p) - len * nor);
    }
    return res;
}

vector<Point> is_sc(Circle c, Line l){
    vector<Point> v = is_lc(c, l), res;
    for (Point p : v)
        if (isis_sp(l, p)) res.push_back(p);
    return res;
}

vector<Line> tangent_cp(Circle c, Point p) {
    vector<Line> ret;
    Point v = c.p - p;
    ld d = abs(v);
    ld l = sqrt(norm(v) - c.r * c.r);
    if (isnan((long double)l)) { return ret; }
    Point v1 = v * Point(l / d,	c.r / d);
    Point v2 = v * Point(l / d, -c.r / d);
    ret.push_back(Line(p, p + v1));
    if (l < eps) return ret;
    ret.push_back(Line(p, p + v2));
    return ret;
}

vector<Line> tangent_cc(Circle c1, Circle c2) {
    vector<Line> ret;
    if (abs(c1.p - c2.p) - (c1.r + c2.r) > -eps) {
        Point center = (c1.p * c2.r + c2.p * c1.r) / (c1.r + c2.r);
        ret = tangent_cp(c1, center);
    }
    if (abs(c1.r - c2.r) > eps) {
        Point out = (-c1.p * c2.r + c2.p * c1.r) / (c1.r - c2.r);
        vector<Line> nret = tangent_cp(c1, out);
        ret.insert(ret.end(), all(nret));
    }
    else {
        Point v = c2.p - c1.p;
        v /= abs(v);
        Point q1 = c1.p + v * Point(0,	1) * c1.r;
        Point q2 = c1.p + v * Point(0, -1) * c1.r;
        ret.push_back(Line(q1, q1 + v));
        ret.push_back(Line(q2, q2 + v));
    }
    return ret;
}

typedef vector<Point> Polygon;

ld area(const Polygon &p) {
    ld res = 0;
    int n = p.size();
    REP(j,n) res += cross(p[j], p[(j+1)%n]);
    return res / 2;
}

bool is_counter_clockwise (const Polygon &poly) {
    ld angle = 0;
    int n = poly.size();
    REP(i,n) {
        Point a = poly[i], b = poly[(i+1)%n], c = poly[(i+2)%n];
        angle += arg((c - b) / (b - a));
    }
    return angle > eps;
}

int is_in_polygon (const Polygon &poly, Point p) {
    ld angle = 0;
    int n = poly.size();
    REP(i,n) {
        Point a = poly[i], b = poly[(i+1)%n];
        if (isis_sp(Line(a, b), p)) return 1;
        angle += arg((b - p) / (a - p));
    }
    return eq(angle, 0) ? 0 : 2;
}

Polygon convex_hull(vector<Point> ps) {
    int n = ps.size();
    int k = 0;
    sort(ps.begin(), ps.end());
    Polygon ch(2 * n);
    for (int i = 0; i < n; ch[k++] = ps[i++])
        while (k >= 2 && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
    for (int i = n - 2, t = k + 1; i >= 0; ch[k++] = ps[i--])
        while (k >= t && ccw(ch[k - 2], ch[k - 1], ps[i]) <= 0) --k;
    ch.resize(k - 1);
    return ch;
}

Polygon convex_cut(const Polygon &ps, Line l) {
    int n = ps.size();
    Polygon Q;
    REP(i,n) {
        Point A = ps[i], B = ps[(i+1)%n];
        Line m = Line(A, B);
        if (ccw(l.a, l.b, A) != -1) Q.push_back(A);
        if (ccw(l.a, l.b, A) * ccw(l.a, l.b, B) < 0 && isis_ll(l, m))
            Q.push_back(is_ll(l, m));
    }
    return Q;
}

void add_point(vector<Point> &ps, Point p) {
    for (Point q : ps) if (abs(q - p) < eps) return;
    ps.push_back(p);
}

typedef int Weight;

struct Edge { int from, to; Weight weight; };
bool operator>(const Edge& e1, const Edge& e2) {
    return e1.weight > e2.weight;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

void add_edge(Graph &g, int from, int to, Weight weight) {
    g[from].push_back((Edge){from, to, weight});
}

Graph segment_arrangement(const vector<Line> &s, const vector<Point> &p) {
    int n = p.size(), m = s.size();
    Graph g(n);
    REP(i,m) {
        vector<pair<ld,int>> vec;
        REP(j,n) if (isis_sp(s[i], p[j]))
            vec.emplace_back(abs(s[i].a - p[j]), j);
        sort(all(vec));
        REP(j,vec.size()-1) {
            int from = vec[j].second, to = vec[j+1].second;
            add_edge(g, from, to, abs(p[from] - p[to]));
        }
    }
    return g;
}

Graph circle_arrangement(const vector<Circle> &c, const vector<Point> &p) {
    int n = p.size(), m = c.size();
    Graph g(n);
    REP(i,m) {
        vector<pair<ld,int>> vec;
        REP(j,n) if (abs(abs(c[i].p - p[j]) - c[i].r) < eps)
            vec.emplace_back(arg(c[i].p - p[j]), j);
        sort(all(vec));
        REP(j,vec.size()-1) {
            int from = vec[j].second, to = vec[j+1].second;
            ld angle = vec[j+1].first - vec[j].first;
            add_edge(g, from, to, angle * c[i].r);
        }
        if (vec.size() >= 2) {
            int from = vec.back().second, to = vec.front().first;
            ld angle = vec.front().first - vec.back().first;
            add_edge(g, from, to, angle * c[i].r);
        }
    }
    return g;
}

vector<vector<int>> polygon;
vector<int> seg2p[1024][1024];

Graph dual_graph(const vector<Line> &s, const vector<Point> &p) {
    int N = p.size();
    polygon.clear();
    REP(i,1024) REP(j,1024) seg2p[i][j].clear();
    vector<vector<tuple<ld,int,bool>>> tup(N);
    REP(i,s.size()) {
        int a = -1, b = -1;
        REP(j,N) if (abs(s[i].a - p[j]) < eps) a = j;
        REP(j,N) if (abs(s[i].b - p[j]) < eps) b = j;
        assert(a >= 0 && b >= 0);
        tup[a].emplace_back(arg(s[i].b - s[i].a), b, false);
        tup[b].emplace_back(arg(s[i].a - s[i].b), a, false);
    }
    REP(i,N) sort(all(tup[i]));
    REP(i,N) {
        REP(j,tup[i].size()) {
            ld angle; int pos = j, from = i, to; bool flag;
            tie(angle, to, flag) = tup[i][j];
            if (flag) continue;
            vector<int> ps;
            while (!flag) {
                ps.push_back(from);
                get<2>(tup[from][pos]) = true;
                seg2p[from][to].push_back(polygon.size());
                seg2p[to][from].push_back(polygon.size());
                angle += pi + eps;
                if (angle > pi) angle -= 2 * pi;
                auto it = lower_bound(all(tup[to]), make_tuple(angle, 0, false));
                if (it == tup[to].end()) it = tup[to].begin();
                from = to; tie(angle, to, flag) = *it;
                pos = it - tup[from].begin();
            }
            polygon.push_back(ps);
        }
    }
    Graph g(polygon.size());
    REP(i,N) REP(j,i) {
        if (seg2p[i][j].size() == 2) {
            int from = seg2p[i][j][0];
            int to = seg2p[i][j][1];
            int len = 1;
            // double len = abs(p[i] - p[j]);
            g[from].push_back((Edge){from, to, len});
            g[to].push_back((Edge){to, from, len});
        }
    }
    return g;
}

const ld zoom = 25;
const ld centerX = 6;
const ld centerY = 5;

void change_color(int r, int g, int b) {
    fprintf(stderr, "c.strokeStyle = 'rgb(%d, %d, %d)';\n", r, g, b);
}

int cordx(Point p) { return 400 + zoom * (p.real() - centerX); }
int cordy(Point p) { return 400 - zoom * (p.imag() - centerY); }

#define cord(p) cordx(p),cordy(p)

void draw_point(Point p) {
    fprintf(stderr, "circle(%d, %d, %d)\n", cord(p), 2);
}

void draw_segment(Line l) {
    fprintf(stderr, "line(%d, %d, %d, %d)\n", cord(l.a), cord(l.b));
}

void draw_line(Line l) {
    Point v = l.b - l.a;
    Line m(l.a - v * Point(1e4, 0), l.b + v * Point(1e4, 0));
    fprintf(stderr, "line(%d, %d, %d, %d)\n", cord(m.a), cord(m.b));
}

void draw_polygon(const Polygon &p) {
    int n = p.size();
    REP(i,n) draw_segment(Line(p[i], p[(i+1)%n]));
}

void draw_circle(Circle c) {
    fprintf(stderr, "circle(%d, %d, %d)\n", cord(c.p), (int)(zoom * c.r));
}
class UnionFind {
    vector<int> par, h;
public:
    UnionFind(int size) {
        par.assign(size, 0);
        h.assign(size, 0);
        REP(i, size) par[i] = i;
    }
    void unite(int u, int v) {
        u = root(u), v = root(v);
        if (u == v) return;
        if (h[u] > h[v]) {
            par[v] = u;
        }
        else if (h[u] < h[v]) {
            par[u] = v;
        }
        else {
            ++h[u];
            par[v] = u;
        }
    }
    bool isUnited(int u, int v) {
        return root(u) == root(v);
    }
    int root(int v) {
        if (par[v] == v) return v;
        return par[v] = root(par[v]);
    }
};
vector<ll> bfs(const Graph& G, const ll s) {
    const ll n = G.size();
    vector<ll> dist(n, linf);
    dist[s] = 0;
    queue<ll> Q; Q.push(s);
    while ( !Q.empty() ) {
        ll v = Q.front(); Q.pop();
        each(e, G[v]) {
            if (dist[v]+1 < dist[e.to]) {
                dist[e.to] = dist[v]+1;
                Q.push(e.to);
            }
        }
    }
    return dist;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    ll n, m;
    while (cin >> n >> m, n || m) {
        vector<Line> lines;
        vector<Point> points;
        rep(i, n) {
            points.pb(input_point());
        }
        rep(i, m) {
            ll a, b; cin >> a >> b; --a, --b;
            lines.pb(Line(points[a], points[b]));
        }
        Graph G = dual_graph(lines, points);
        const ll V = G.size();
        // rep(i, polygon.size()) {
        //     each(id, polygon[i]) {
        //         Point p = points[id];
        //         cout << "(" << p.real() << ", " << p.imag() << ")";
        //     }
        //     cout << endl;
        // }
        // ll s = V-1;
        ll s = 0;
        vector<ll> dist = bfs(G, s);
        ll ans = 0;
        rep(i, V) chmax(ans, dist[i]);
        cout << ans << endl;
    }
}
accuracy: 0.125
time_ms: 20
memory_kb: 28048
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i, n) for ( int i = 0; i < n; i++ )
#define INF (1<<21)
#define MAX 104
int n, m;
bool V[MAX][MAX];
int T[MAX][MAX];
int F[MAX][MAX];
int face;
vector<int> G[MAX];
pair<int, int> P[MAX];
vector<vector<pair<int, int> > > R; // room;

double angle(int s, int t){
  return atan2(P[t].second - P[s].second, P[t].first - P[s].first);
}

void parse(int s, int t, bool isouter, int f){
  if ( V[s][t] || s == t ) return;
  int cur1 = s, cur2 = t;
  vector<pair<int, int> > room;
  while(1){
    if ( V[cur1][cur2] ) break;
    V[cur1][cur2] = true;
    F[cur1][cur2] = f;
    room.push_back(make_pair(cur1, cur2));
    int nx;
    rep(i, G[cur2].size() ){
      if ( G[cur2][i] == cur1 ){ nx = i; break; } // next node after counter-clock
    }
    nx = (nx+1)%G[cur2].size();
    cur1 = cur2;
    cur2 = G[cur2][nx];
  }
  R.push_back(room);
}

bool isConnected(vector<pair<int, int> > &c1, vector<pair<int, int> > &c2){
  for ( int i = 0; i < c1.size(); i++ ){
    for ( int j = 0; j < c2.size(); j++ ){
      pair<int, int> p1 = c1[i];
      pair<int, int> p2 = c2[j];
      if ( p1 == p2 ) return true;
      swap(p2.first, p2.second);
      if ( p1 == p2 ) return true;
    }
  }
  return false;
}

vector<vector<int> > makeGraph(){
  R.clear();
  // sort by angle
  rep(s, n) {
    for ( int e = G[s].size()-2; e >= 0; e--){
      for ( int j = 0; j <= e; j++ ){
    	  if ( angle(s, G[s][j]) > angle(s, G[s][j+1]) ) swap(G[s][j], G[s][j+1]);
      }
    }
  }

  rep(i, n) rep(j, n) V[i][j] = false;

  int bottom = 0;
  rep(i, n){
    if ( P[i].second == P[bottom].second ){
      if ( P[i].first < P[bottom].first ) bottom = i;
    } else {
      if ( P[i].second < P[bottom].second ) bottom = i;
    }
  }

  face = 0;
  rep(i, n) rep(j, n) F[i][j] = -1;

  parse(bottom, G[bottom][0], true, face); // the outer

  rep(s, n)  rep(j, G[s].size()){
    int t =  G[s][j];
    parse(s, t, false, ++face);
  }

  rep(i, n) rep(j, n) {
    if ( F[i][j] == -1 ){
      assert( F[j][i] == -1);
      continue;
    }
    assert( F[i][j] != F[j][i] );
  }


  vector<vector<int> > g;
  g.resize(R.size());
  for ( int i = 0; i < R.size()-1; i++ ){
    for ( int j = i+1; j < R.size(); j++ ){
      if ( isConnected(R[i], R[j])) {
    g[i].push_back(j);
    g[j].push_back(i);
      }
    }
  }

  assert( n - m + R.size() == 2 );

  return g;
}

int bfs(vector<vector<int> > g){
  vector<int> d;
  d.resize(g.size());
  rep(i, g.size()) d[i] = INF;
  queue<int> Q;
  int u, v;
  for ( d[0] = 0, Q.push(0); !Q.empty(); ){
    u = Q.front(); Q.pop();
    for ( int i = 0; i < g[u].size(); i++ ){
      int v = g[u][i];
      if ( d[v] != INF ) continue;
      d[v] = d[u] + 1;
      Q.push(v);
    }
  }
  int maxv = 0;
  for ( int i = 0; i < d.size(); i++) maxv = max(maxv, d[i]);
  return maxv;
}

int main(){
  while(1){
    cin >> n >> m;
    if ( n == 0 ) break;
    assert( 3 <= n && n <= 100 );
    assert( n <= m && m <= 300 );
    set<pair<int, int> > S;
    rep(i, n) {cin >> P[i].first >> P[i].second;S.insert( P[i]) ;}
    assert( S.size() == n );
    rep(i, n) G[i].clear();
    map<pair<int, int>, bool> vis;
    rep(i, m){
      int s, t; cin >> s >> t; s--; t--;
      G[s].push_back(t);G[t].push_back(s);
      T[s][t] = T[t][s] = (i+1); // 0 = outer
      vis[make_pair(min(s, t), max(s,t))] = true;
    }

    cout << bfs(makeGraph()) << endl;
  }
  return 0;

}
accuracy: 1
time_ms: 10
memory_kb: 3504
final_rank: 2

code_snippet: //
// [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);
  }
}
accuracy: 1
time_ms: 20
memory_kb: 3596
final_rank: 7