Problem p00268 (C++) — buggy submission, verdict: Runtime Error

#include <bits/stdc++.h>

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

template <class T> ostream &operator<<(ostream &os, const V<T> &v) {
  cout << "[";
  for (auto p : v)
    cout << p << ", ";
  cout << "]";
  return os;
}

template <class T> struct Pt2 {
  T x, y;
  Pt2() {}
  Pt2(T _x, T _y) : x(_x), y(_y) {}
  Pt2 operator+(const Pt2 &r) const { return Pt2(x + r.x, y + r.y); }
  Pt2 operator-(const Pt2 &r) const { return Pt2(x - r.x, y - r.y); }

  Pt2 operator-() const { return Pt2(-x, -y); }

  T abs() const { return sqrt(x * x + y * y); }
  T rabs() const { return max(x, y); } // robust abs
  T arg() const { return atan2(y, x); }
};
template <class T> ostream &operator<<(ostream &os, const Pt2<T> &p) {
  os << "(" << p.x << ", " << p.y << ")";
  return os;
}

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

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

int sgn(D a) {
  if (abs(a) <= EPS)
    return 0;
  return (a < 0) ? -1 : 1;
}
// relative sign
int rsgn(D a, D f) {
  if (abs(a) <= f * EPS)
    return 0;
  return (a < 0) ? -1 : 1;
}
bool near(P a, P b) { return !sgn((a - b).abs()); }

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

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

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

struct L {
  P s, t;
  L() {}
  L(P s, P t) : s(s), t(t) {}
  P vec() const { return t - s; }
  D abs() const { return vec().abs(); }
  D arg() const { return vec().arg(); }
};
int ccw(L l, P p) { return ccw(l.s, l.t, p); }

using Pol = V<P>;

// cycle at
const P &c_at(const Pol &pol, int i) {
  int n = int(pol.size());
  assert(0 <= i && i < 2 * n);
  return pol[(i < n) ? i : i - n];
}

D area2_noabs(const Pol &p) {
  D u = 0;
  for (size_t i = 0; i < p.size(); i++) {
    u += cross(p[i], c_at(p, i + 1));
  }
  return u;
}

// -1: cw, 0: line, 1: ccw
int is_ccw(const Pol &p) { return sgn(area2_noabs(p)); }

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

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

  VV<int> vis(n), rev(n);
  for (int i = 0; i < n; i++) {
    vis[i] = V<int>(g[i].size(), -3);
    for (int d : g[i]) {
      rev[i].push_back(mp[Pi(d, i)]);
    }
  }

  V<Pol> pols;
  int idc = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < int(g[i].size()); j++) {
      if (vis[i][j] != -3)
        continue;
      Pol pol;
      int p = i, idx = j;
      while (vis[p][idx] != -2) {
        pol.push_back(ps[p]);
        vis[p][idx] = -2;
        int np = g[p][idx];
        int nidx = rev[p][idx] + 1;
        if (nidx == int(g[np].size()))
          nidx = 0;

        p = np;
        idx = nidx;
      }
      int id = -1;
      if (is_ccw(pol) == 1) {
        id = idc;
        pols.push_back(pol);
        idc++;
      }
      //            cout << "FIND " << id << " " << is_ccw(pol) << " " << pol <<
      //            endl;
      while (vis[p][idx] == -2) {
        vis[p][idx] = id;
        int np = g[p][idx];
        int nidx = rev[p][idx] + 1;
        if (nidx == int(g[np].size()))
          nidx = 0;

        p = np;
        idx = nidx;
      }
    }
  }
  VV<int> g2(idc + 1);

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < int(g[i].size()); j++) {
      int x = vis[i][j], y = vis[g[i][j]][rev[i][j]];
      if (x == -1)
        x = idc;
      if (y == -1)
        y = idc;
      g2[x].push_back(y);
    }
  }
  for (int i = 0; i <= idc; i++) {
    sort(begin(g2[i]), end(g2[i]));
    g2[i].erase(unique(begin(g2[i]), end(g2[i])), end(g2[i]));
  }

  return DualGraph{pols, g2};
}

bool solve() {
  int c, w;
  cin >> c >> w;
  if (!c)
    return false;

  V<P> p(c);
  for (int i = 0; i < c; i++) {
    D x, y;
    cin >> x >> y;
    p[i] = P(x, y);
  }

  VV<int> g(c);
  for (int i = 0; i < w; i++) {
    int s, t;
    cin >> s >> t;
    s--;
    t--;
    g[s].push_back(t);
    g[t].push_back(s);
  }

  auto dg = dualGraph(p, g);
  int n = int(dg.g.size());

  // cout << "DEBUG: " << endl;
  // cout << n << endl;
  // for (int i = 0; i < n-1; i++) {
  //     for (P p: dg.pols[i]) {
  //         cout << p << ", ";
  //     } cout << endl;
  // }
  V<int> dist(n, TEN(9));

  queue<int> q;
  dist[n - 1] = 0;
  q.push(n - 1);
  while (q.size()) {
    int p = q.front();
    q.pop();
    for (int d : dg.g[p]) {
      if (dist[d] <= dist[p] + 1)
        continue;
      dist[d] = dist[p] + 1;
      q.push(d);
    }
  }
  int ma = -1;
  for (int i = 0; i < n; i++)
    ma = max(ma, dist[i]);
  cout << ma << endl;
  return true;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(20);

  while (solve()) {
  }
  return 0;
}


Error: 0

Fixed submission:

#include <bits/stdc++.h>

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

template <class T> ostream &operator<<(ostream &os, const V<T> &v) {
  cout << "[";
  for (auto p : v)
    cout << p << ", ";
  cout << "]";
  return os;
}

template <class T> struct Pt2 {
  T x, y;
  Pt2() {}
  Pt2(T _x, T _y) : x(_x), y(_y) {}
  Pt2 operator+(const Pt2 &r) const { return Pt2(x + r.x, y + r.y); }
  Pt2 operator-(const Pt2 &r) const { return Pt2(x - r.x, y - r.y); }

  Pt2 operator-() const { return Pt2(-x, -y); }

  T abs() const { return sqrt(x * x + y * y); }
  T rabs() const { return max(x, y); } // robust abs
  T arg() const { return atan2(y, x); }
};
template <class T> ostream &operator<<(ostream &os, const Pt2<T> &p) {
  os << "(" << p.x << ", " << p.y << ")";
  return os;
}

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

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

int sgn(D a) {
  if (abs(a) <= EPS)
    return 0;
  return (a < 0) ? -1 : 1;
}
// relative sign
int rsgn(D a, D f) {
  if (abs(a) <= f * EPS)
    return 0;
  return (a < 0) ? -1 : 1;
}
bool near(P a, P b) { return !sgn((a - b).abs()); }

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

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

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

struct L {
  P s, t;
  L() {}
  L(P s, P t) : s(s), t(t) {}
  P vec() const { return t - s; }
  D abs() const { return vec().abs(); }
  D arg() const { return vec().arg(); }
};
int ccw(L l, P p) { return ccw(l.s, l.t, p); }

using Pol = V<P>;

// cycle at
const P &c_at(const Pol &pol, int i) {
  int n = int(pol.size());
  assert(0 <= i && i < 2 * n);
  return pol[(i < n) ? i : i - n];
}

D area2_noabs(const Pol &p) {
  D u = 0;
  for (size_t i = 0; i < p.size(); i++) {
    u += cross(p[i], c_at(p, i + 1));
  }
  return u;
}

// -1: cw, 0: line, 1: ccw
int is_ccw(const Pol &p) { return sgn(area2_noabs(p)); }

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

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

  VV<int> vis(n), rev(n);
  for (int i = 0; i < n; i++) {
    vis[i] = V<int>(g[i].size(), -3);
    for (int d : g[i]) {
      rev[i].push_back(mp[Pi(d, i)]);
    }
  }

  V<Pol> pols;
  int idc = 0;
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < int(g[i].size()); j++) {
      if (vis[i][j] != -3)
        continue;
      Pol pol;
      int p = i, idx = j;
      while (vis[p][idx] != -2) {
        pol.push_back(ps[p]);
        vis[p][idx] = -2;
        int np = g[p][idx];
        int nidx = rev[p][idx] + 1;
        if (nidx == int(g[np].size()))
          nidx = 0;

        p = np;
        idx = nidx;
      }
      int id = -1;
      if (is_ccw(pol) == 1) {
        id = idc;
        pols.push_back(pol);
        idc++;
      }
      //            cout << "FIND " << id << " " << is_ccw(pol) << " " << pol <<
      //            endl;
      while (vis[p][idx] == -2) {
        vis[p][idx] = id;
        int np = g[p][idx];
        int nidx = rev[p][idx] + 1;
        if (nidx == int(g[np].size()))
          nidx = 0;

        p = np;
        idx = nidx;
      }
    }
  }

  VV<int> g2(idc + 1);

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < int(g[i].size()); j++) {
      int x = vis[i][j], y = vis[g[i][j]][rev[i][j]];
      if (x == -1)
        x = idc;
      if (y == -1)
        y = idc;
      g2[x].push_back(y);
    }
  }

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

  return DualGraph{pols, g2};
}

bool solve() {
  int c, w;
  cin >> c >> w;
  if (!c)
    return false;

  V<P> p(c);
  for (int i = 0; i < c; i++) {
    D x, y;
    cin >> x >> y;
    p[i] = P(x, y);
  }

  VV<int> g(c);
  for (int i = 0; i < w; i++) {
    int s, t;
    cin >> s >> t;
    s--;
    t--;
    g[s].push_back(t);
    g[t].push_back(s);
  }

  auto dg = dualGraph(p, g);
  int n = int(dg.g.size());

  /*    cout << "DEBUG: " << endl;
      cout << n << endl;
      for (int i = 0; i < n-1; i++) {
          for (P p: dg.pols[i]) {
              cout << p << ", ";
          } cout << endl;
      }*/
  V<int> dist(n, TEN(9));

  queue<int> q;
  dist[n - 1] = 0;
  q.push(n - 1);
  while (q.size()) {
    int p = q.front();
    q.pop();
    for (int d : dg.g[p]) {
      if (dist[d] <= dist[p] + 1)
        continue;
      dist[d] = dist[p] + 1;
      q.push(d);
    }
  }
  int ma = -1;
  for (int i = 0; i < n; i++)
    ma = max(ma, dist[i]);
  cout << ma << endl;
  return true;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << setprecision(20);

  while (solve()) {
  }
  return 0;
}