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

#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <vector>

#include <cstring>

// ???, ????????????
typedef std::complex<double> Point;
typedef Point Vector;

namespace std {
bool operator<(const Point &a, const Point &b) {
  return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag();
}

istream &operator>>(istream &is, Point &a) {
  double x, y;
  is >> x >> y;
  a = Point(x, y);
  return is;
}

ostream &operator<<(ostream &os, Point a) {
  return os << a.real() << " " << a.imag();
}
} // namespace std

// ??´???
struct Line {
  Point p1, p2;
  Line() {}
  Line(const Point &p1, const Point &p2) : p1(p1), p2(p2) {}
};
typedef Line Segment;

namespace std {
istream &operator>>(istream &is, Line &a) { return is >> a.p1 >> a.p2; }
} // namespace std

// ???
struct Circle {
  Point p;
  double r;
  Circle() {}
  Circle(const Point &p, double r) : p(p), r(r) {}
};

namespace std {
istream &operator>>(istream &is, Circle &a) { return is >> a.p >> a.r; }
} // namespace std

// ????§???¢
typedef std::vector<Point> Polygon;

const double EPS = 1e-12;
const double INF = 1e12;
const double PI = acos(-1.0);

// ????????¨??????????????¢???
enum CCW {
  COUNTER_CLOCKWISE = 1,
  CLOCKWISE = -1,
  ONLINE_BACK = 2,
  ONLINE_FRONT = -2,
  ON_SEGMENT = 0,
};

// ?????¢????£????????????¢???
enum {
  OUT = 0,
  ON = 1,
  IN = 2,
};

// a ??? 2 ??? (a ^ 2)
double SQ(double a);

// ?????????????????????????????¢??°
bool EQ(double a, double b);
bool NEQ(double a, double b);
bool LT(double a, double b);
bool GT(double a, double b);
bool LEQ(double a, double b);
bool GEQ(double a, double b);

// ??§?????? <=> ?????°?????????
double toDeg(double t);
double toRad(double t);

// ????????? (dot(a, a))
double norm(const Vector &a);

// ??????, ??????
double dot(const Vector &a, const Vector &b);
double cross(const Vector &a, const Vector &b);

// ??´???, ??????
bool orthogonal(const Segment &s1, const Segment &s2);
bool parallel(const Segment &s1, const Segment &s2);

// ?°???±, ????°?
Point project(const Line &l, const Point &p);
Point reflect(const Line &l, const Point &p);

// ?????? (p0, p1) ??¨??? p2 ???????????¢???
int ccw(const Point &p0, const Point &p1, const Point &p2);

// ????????????
bool intersectLP(const Line &l, const Point &p);
bool intersectLL(const Line &l1, const Line &l2);
bool intersectLS(const Line &l, const Segment &s);
bool intersectSP(const Segment &s, const Point &p);
bool intersectSS(const Segment &s1, const Segment &s2);
int intersectCP(const Circle &c, const Point &p);
bool intersectCL(const Circle &c, const Line &l);
int intersectCS(const Circle &c, const Segment &s);
int intersectCC(const Circle &c1, const Circle &c2);

// ?????¢
double distanceLP(const Line &l, const Point &p);
double distanceLL(const Line &l1, const Line &l2);
double distanceLS(const Line &l, const Segment &s);
double distanceSP(const Segment &s, const Point &p);
double distanceSS(const Segment &s1, const Segment &s2);
double distanceCP(const Circle &c, const Point &p);
double distanceCL(const Circle &c, const Line &l);
double distanceCS(const Circle &c, const Segment &s);
double distanceCC(const Circle &c1, const Circle &c2);

// ??????
Point crossPointLL(const Line &l1, const Line &l2);
Point crossPointLS(const Line &l, const Segment &s);
Point crossPointSS(const Segment &s1, const Segment &s2);
std::vector<Point> crossPointCL(const Circle &c, const Line &l);
std::vector<Point> crossPointCS(const Circle &c, const Segment &s);
std::vector<Point> crossPointCC(const Circle &c1, const Circle &c2);

double SQ(double a) { return a * a; }

bool EQ(double a, double b) { return std::abs(a - b) < EPS; }

bool NEQ(double a, double b) { return !EQ(a, b); }

bool LT(double a, double b) { return a - b < -EPS; }

bool GT(double a, double b) { return a - b > EPS; }

bool LEQ(double a, double b) { return !GT(a, b); }

bool GEQ(double a, double b) { return !LT(a, b); }

double toDeg(double t) { return t * 180 / PI; }

double toRad(double t) { return t / 180 * PI; }

double norm(const Vector &a) { return SQ(a.real()) + SQ(a.imag()); }

double dot(const Vector &a, const Vector &b) { return (conj(a) * b).real(); }

double cross(const Vector &a, const Vector &b) { return (conj(a) * b).imag(); }

// AOJ CGL_2_A
bool orthogonal(const Segment &s1, const Segment &s2) {
  return EQ(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

// AOJ CGL_2_A
bool parallel(const Segment &s1, const Segment &s2) {
  return EQ(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

// AOJ CGL_1_A
Point project(const Line &l, const Point &p) {
  Vector base = l.p2 - l.p1;
  double r = dot(p - l.p1, base) / norm(base);
  return l.p1 + base * r;
}

// AOJ CGL_1_B
Point reflect(const Line &l, const Point &p) {
  return p + (project(l, p) - p) * 2.0;
}

// AOJ CGL_1_C
int ccw(const Point &p0, const Point &p1, const Point &p2) {
  Vector a = p1 - p0;
  Vector b = p2 - p0;
  if (GT(cross(a, b), 0.0))
    return COUNTER_CLOCKWISE;
  if (LT(cross(a, b), 0.0))
    return CLOCKWISE;
  if (LT(dot(a, b), 0.0))
    return ONLINE_BACK;
  if (LT(norm(a), norm(b)))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}

bool intersectLP(const Line &l, const Point &p) {
  return LEQ(std::abs(cross(l.p1 - p, l.p2 - p)), 0.0);
}

bool intersectLL(const Line &l1, const Line &l2) {
  return !parallel(l1, l2) ||
         LEQ(std::abs(cross(l1.p2 - l1.p1, l2.p1 - l1.p1)), 0.0);
}

bool intersectLS(const Line &l, const Segment &s) {
  return LEQ(cross(l.p2 - l.p1, s.p1 - l.p1) * cross(l.p2 - l.p1, s.p2 - l.p1),
             0.0);
}

bool intersectSP(const Segment &s, const Point &p) {
  return norm(s.p1 - p) + norm(s.p2 - p) - norm(s.p2 - s.p1) < EPS;
}

// CGL_2_B
bool intersectSS(const Segment &s1, const Segment &s2) {
  return ccw(s1.p1, s1.p2, s2.p1) * ccw(s1.p1, s1.p2, s2.p2) <= 0 &&
         ccw(s2.p1, s2.p2, s1.p1) * ccw(s2.p1, s2.p2, s1.p2) <= 0;
}

int intersectCP(const Circle &c, const Point &p) {
  double dd = norm(c.p - p);
  if (LT(dd, SQ(c.r)))
    return IN;
  if (EQ(dd, SQ(c.r)))
    return ON;
  return OUT;
}

bool intersectCL(const Circle &c, const Line &l) {
  double d = distanceLP(l, c.p);
  return LEQ(d, c.r);
}

int intersectCS(const Circle &c, const Segment &s) {
  double dd1 = norm(c.p - s.p1);
  double dd2 = norm(c.p - s.p2);
  if (LT(dd1, SQ(c.r)) && LT(dd2, SQ(c.r)))
    return IN;
  if (GT(distanceCS(c, s), 0.0))
    return OUT;
  return ON;
}

// c1 ??? c2 ???????????????????????¨??? IN
// c1 ??? c2 ????????£???????????¨??? ON
// c1 ??? c2 ?????????????????¨??? OUT
int intersectCC(const Circle &c1, const Circle &c2) {
  if (GT(norm(c1.p - c2.p), SQ(c1.r + c2.r)))
    return OUT;
  if (LT(norm(c1.p - c2.p), SQ(c2.r)))
    return IN;
  if (LT(norm(c1.p - c2.p), SQ(c1.r)))
    return OUT;
  return ON;
}

double distanceLP(const Line &l, const Point &p) {
  return std::abs(cross(l.p2 - l.p1, p - l.p1)) / std::abs(l.p2 - l.p1);
}

double distanceLL(const Line &l1, const Line &l2) {
  if (intersectLL(l1, l2))
    return 0.0;
  return distanceLP(l1, l2.p1);
}

double distanceLS(const Line &l, const Segment &s) {
  if (intersectLS(l, s))
    return 0.0;
  return std::min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}

double distanceSP(const Segment &s, const Point &p) {
  if (dot(s.p2 - s.p1, p - s.p1) < 0.0)
    return std::abs(p - s.p1);
  if (dot(s.p1 - s.p2, p - s.p2) < 0.0)
    return std::abs(p - s.p2);
  return distanceLP(s, p);
}

// AOJ CGL_2_D
double distanceSS(const Segment &s1, const Segment &s2) {
  if (intersectSS(s1, s2))
    return 0.0;
  return std::min(std::min(distanceSP(s1, s2.p1), distanceSP(s1, s2.p2)),
                  std::min(distanceSP(s2, s1.p1), distanceSP(s2, s1.p2)));
}

double distanceCP(const Circle &c, const Point &p) {
  return std::abs(std::abs(c.p - p) - c.r);
}

double distanceCL(const Circle &c, const Line &l) {
  if (intersectCL(c, l))
    return 0.0;
  return distanceLP(l, c.p) - c.r;
}

double distanceCS(const Circle &c, const Segment &s) {
  if (intersectCS(c, s))
    return 0.0;
  return std::min(distanceCP(c, s.p1), distanceCP(c, s.p2));
}

double distanceCC(const Circle &c1, const Circle &c2) {
  if (intersectCC(c1, c2) == ON)
    return 0.0;
  if (intersectCC(c1, c2) == IN) {
    return c2.r - (std::abs(c1.p - c2.p) + c1.r);
  }
  if (intersectCC(c2, c1) == IN) {
    return c1.r - (std::abs(c1.p - c2.p) + c2.r);
  }
  return (c1.r + c2.r) - (c1.r + c2.r);
}

Point crossPointLL(const Line &l1, const Line &l2) {
  assert(intersectLL(l1, l2));
  Vector base = l2.p2 - l2.p1;
  double d1 = std::abs(cross(base, l1.p1 - l2.p1));
  double d2 = std::abs(cross(base, l1.p2 - l2.p1));
  double t = d1 / (d1 + d2);
  return l1.p1 + (l1.p2 - l1.p1) * t;
}

Point crossPointLS(const Line &l, const Segment &s) {
  assert(intersectLS(l, s));
  return crossPointLL(l, s);
}

Point crossPointSS(const Segment &s1, const Segment &s2) {
  assert(intersectSS(s1, s2));
  return crossPointSS(s1, s2);
}

std::vector<Point> crossPointCL(const Circle &c, const Line &l) {
  if (!intersectCL(c, l))
    return std::vector<Point>();
  std::vector<Point> ret;
  Vector proj = project(l, c.p);
  Vector e = (l.p2 - l.p1) / std::abs(l.p2 - l.p1);
  double base = sqrt(SQ(c.r) - norm(proj - c.p));
  ret.push_back(proj + e * base);
  ret.push_back(proj - e * base);
  return ret;
}

std::vector<Point> crossPointCS(const Circle &c, const Segment &s) {
  std::vector<Point> ret = crossPointCL(c, s);
  for (int i = 0; i < ret.size(); i++) {
    if (!intersectCP(c, ret[i])) {
      swap(ret[i], ret.back());
      ret.pop_back();
      i--;
    }
  }
  return ret;
}

std::vector<Point> crossPointCC(const Circle &c1, const Circle &c2) {
  if (!intersectCC(c1, c2))
    return std::vector<Point>();
  std::vector<Point> ret;
  double d = std::abs(c1.p - c2.p);
  double a = std::acos((SQ(c1.r) + SQ(d) - SQ(c2.r)) / (2 * c1.r * d));
  double t = std::arg(c2.p - c1.p);
  ret.push_back(c1.p + std::polar(c1.r, t + a));
  ret.push_back(c1.p + std::polar(c1.r, t - a));
  return ret;
}

namespace {
enum { DIRECTED, UNDIRECTED };
const int GRAPH_TYPE = DIRECTED;

typedef int Weight;
const Weight INF = 1 << 28;

struct Edge {
  int src, dst;
  Weight weight;
  Edge() {}
  Edge(int src, int dst, Weight weight = 1)
      : src(src), dst(dst), weight(weight) {}
  bool operator<(const Edge &t) const { return weight < t.weight; }
};

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

void addEdge(Graph &g, int src, int dst, int weight = 1) {
  g[src].push_back(Edge(src, dst, weight));
  if (GRAPH_TYPE == UNDIRECTED)
    g[dst].push_back(Edge(dst, src, weight));
};

Graph transpose(const Graph &g) {
  Graph rg(g.size());
  for (int i = 0; i < g.size(); i++) {
    for (int j = 0; j < g[i].size(); j++) {
      addEdge(rg, g[i][j].dst, g[i][j].src, g[i][j].weight);
    }
  }
  return rg;
}

void dfs_(const Graph &g, int v, bool *used, std::vector<int> &vs) {
  used[v] = true;
  for (int i = 0; i < g[v].size(); i++) {
    int to = g[v][i].dst;
    if (!used[to])
      dfs_(g, to, used, vs);
  }
  vs.push_back(v);
}

void rdfs_(const Graph &g, int v, int k, bool *used, std::vector<int> &cmp) {
  used[v] = true;
  cmp[v] = k;
  for (int i = 0; i < g[v].size(); i++) {
    int to = g[v][i].dst;
    if (!used[to])
      rdfs_(g, to, k, used, cmp);
  }
}

int scc(const Graph &g, std::vector<int> &cmp) {
  Graph rg = transpose(g);
  std::vector<int> vs;
  bool *used = new bool[g.size()];
  cmp.resize(g.size());

  std::memset(used, false, g.size());
  for (int v = 0; v < g.size(); v++) {
    if (!used[v])
      dfs_(g, v, used, vs);
  }

  std::memset(used, false, g.size());
  int k = 0;
  for (int i = vs.size() - 1; i >= 0; i--) {
    if (!used[vs[i]])
      rdfs_(rg, vs[i], k++, used, cmp);
  }

  delete used;
  return k;
}
} // namespace

using namespace std;

int n;
double d;
vector<Polygon> tri;
vector<Polygon> rect;

bool contains(const Polygon &g, const Point &p) {
  for (int i = 0; i < g.size(); i++) {
    int t = ccw(g[i], g[(i + 1) % g.size()], p);
    if (t == CLOCKWISE)
      return false;
    if (t == ON_SEGMENT)
      return true;
  }
  return true;
}

bool intersect(const Polygon &g, const Polygon &h) {
  for (int i = 0; i < g.size(); i++) {
    for (int j = 0; j < h.size(); j++) {
      Segment s(g[i], g[(i + 1) % g.size()]);
      Segment t(h[j], h[(j + 1) % h.size()]);
      if (LEQ(distanceSS(s, t), 0.01))
        return true;
    }
  }

  for (int i = 0; i < g.size(); i++) {
    if (contains(h, g[i]))
      return true;
  }

  for (int i = 0; i < h.size(); i++) {
    if (contains(g, h[i]))
      return true;
  }

  return false;
}

int solve() {
  rect.assign(n, Polygon(4));

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < 3; j++) {
      if (EQ(norm(tri[i][j] - tri[i][(j + 1) % 3]),
             norm(tri[i][j] - tri[i][(j + 2) % 3]))) {
        swap(tri[i][0], tri[i][j]);
      }
    }
    if (ccw(tri[i][1], tri[i][2], tri[i][0]) == CLOCKWISE) {
      swap(tri[i][1], tri[i][2]);
    }

    Vector s = tri[i][2] - tri[i][1];
    Vector normal = s / abs(s) * Vector(0, 1) * d;
    rect[i][0] = tri[i][1];
    rect[i][1] = tri[i][2];
    rect[i][2] = tri[i][2] + normal;
    rect[i][3] = tri[i][1] + normal;
  }

  Graph graph(n);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      if (i == j)
        continue;
      if (intersect(rect[i], tri[j])) {
        addEdge(graph, i, j);
      }
    }
  }

  vector<int> cmp;
  int v = scc(graph, cmp);
  int mat[100][100] = {};
  int in[100] = {};
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < graph[i].size(); j++) {
      int src = cmp[i];
      int dst = cmp[graph[i][j].dst];
      if (src == dst)
        continue;
      if (mat[src][dst]++)
        continue;
      in[dst]++;
    }
  }
  int res = 0;
  for (int i = 0; i < v; i++) {
    if (in[i] == 0)
      res++;
  }
  return res;
}

int main() {
  std::cout << std::fixed << std::setprecision(12);

  while (cin >> n >> d, n) {
    tri.assign(n, Polygon(3));
    for (int i = 0; i < n; i++) {
      for (int j = 0; j < 3; j++) {
        cin >> tri[i][j];
      }
    }
    cout << solve() << endl;
  }
}

Error: -11

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

namespace geometry {
// ???????????§??????

typedef complex<double> Point;

struct Segment {
  Point p1, p2;
  Segment(const Point &p1 = Point(), const Point &p2 = Point())
      : p1(p1), p2(p2) {}
};

struct Circle {
  Point p;
  double r;
  Circle(const Point &p = Point(), double r = 0.0) : p(p), r(r) {}
};

typedef Point Vector;
typedef Segment Line;
typedef vector<Point> Polygon;

// ??\\??????

inline istream &operator>>(istream &is, Point &p) {
  double x, y;
  is >> x >> y;
  p.real(x), p.imag(y);
  return is;
}

inline istream &operator>>(istream &is, Segment &s) {
  return is >> s.p1 >> s.p2;
}

inline istream &operator>>(istream &is, Circle &c) { return is >> c.p >> c.r; }

inline ostream &operator<<(ostream &os, const Segment &s) {
  return os << "{" << s.p1 << ", " << s.p2 << "}";
}

inline ostream &operator<<(ostream &os, const Circle &c) {
  return os << "{" << c.p << ", " << c.r << "}";
}

inline ostream &operator<<(ostream &os, const Polygon &g) {
  os << "{";
  for (int i = 0; i < g.size(); i++) {
    if (i)
      os << ", ";
    os << g[i];
  }
  return os << "}";
}

// ?????°, ??????

const double PI = acos(-1);
const double EPS = 1e-1;
const double INF = 1e16;
const int COUNTER_CLOCKWISE = 1;
const int CLOCKWISE = -1;
const int ONLINE_BACK = 2;
const int ONLINE_FRONT = -2;
const int ON_SEGMENT = 0;
const int OUT = 0;
const int ON = 1;
const int IN = 2;

inline double square(double a) { return a * a; }
inline bool equal(double a, double b) { return abs(a - b) < EPS; }
inline bool equalVector(const Vector &a, const Vector &b) {
  return equal(a.real(), b.real()) && equal(a.imag(), b.imag());
}
inline double norm(const Point &a) {
  return square(a.real()) + square(a.imag());
}
inline double dot(const Point &a, const Point &b) {
  return (conj(a) * b).real();
}
inline double cross(const Point &a, const Point &b) {
  return (conj(a) * b).imag();
}
inline double toDeg(double t) { return t / PI * 180; }
inline double toRad(double t) { return t / 180 * PI; }

#define curr(v, i) v[i]
#define next(v, i) v[(i + 1) % v.size()]
#define prev(v, i) v[(i - 1 + v.size()) % v.size()]

// ????????¢??° (x ??§?¨?, y ??§?¨?, ????§?)
// ????§?????????????????????? Point rp ?????£??\\????????????

bool cmpx(const Point &a, const Point &b) {
  if (!equal(a.real(), b.real()))
    return a.real() < b.real();
  return b.imag() < b.imag();
}

bool cmpy(const Point &a, const Point &b) {
  if (!equal(a.imag(), b.imag()))
    return a.imag() < b.imag();
  return a.real() < b.real();
}

Point rp;
bool cmparg(const Point &a, const Point &b) {
  double rada = arg(a - rp);
  if (rada < 0.0)
    rada += 2 * PI;
  double radb = arg(b - rp);
  if (radb < 0.0)
    radb += 2 * PI;
  if (!equal(rada, radb))
    return rada < radb;
  return norm(a) < norm(b);
}

// ??´???, ??????

bool orthgonal(const Vector &a, const Vector &b) {
  return equal(dot(a, b), 0.0);
}

bool parallel(const Vector &a, const Vector &b) {
  return equal(cross(a, b), 0.0);
}

// ????°?, ?°???±

Point project(const Segment &s, const Point &p) {
  Vector base = s.p2 - s.p1;
  double r = dot(p - s.p1, base) / norm(base);
  return s.p1 + base * r;
}

Point reflect(const Segment &s, const Point &p) {
  return p + (project(s, p) - p) * 2.0;
}

// ??????????????????

int ccw(const Point &p0, const Point &p1, const Point &p2) {
  Vector a = p1 - p0;
  Vector b = p2 - p0;
  if (cross(a, b) > EPS)
    return COUNTER_CLOCKWISE;
  if (cross(a, b) < -EPS)
    return CLOCKWISE;
  if (dot(a, b) < -EPS)
    return ONLINE_BACK;
  if (norm(a) > norm(b))
    return ONLINE_FRONT;
  return ON_SEGMENT;
}

// ?????¢

double distanceLP(const Line &l, const Point &p) {
  return abs(cross(l.p2 - l.p1, p - l.p1) / abs(l.p2 - l.p1));
}

double distanceSP(const Segment &s, const Point &p) {
  if (dot(s.p2 - s.p1, p - s.p1) < 0.0)
    return abs(p - s.p1);
  if (dot(s.p1 - s.p2, p - s.p2) < 0.0)
    return abs(p - s.p2);
  return distanceLP(s, p);
}

bool intersect(const Segment &s1, const Segment &s2);
double distance(const Segment &s1, const Segment &s2) {
  if (intersect(s1, s2))
    return 0.0;
  return min(min(distanceSP(s1, s2.p1), distance(s1, s2.p2)),
             min(distanceSP(s2, s1.p1), distance(s2, s1.p2)));
}

// ????????????

bool intersect(const Segment &s1, const Segment &s2) {
  return ccw(s1.p1, s1.p2, s2.p1) * ccw(s1.p1, s1.p2, s2.p2) <= 0 &&
         ccw(s2.p1, s2.p2, s1.p1) * ccw(s2.p1, s2.p2, s1.p2) <= 0;
}

int intersect(const Circle &c, const Segment &s) {
  // ???????????° (0 ~ 2) ?????????
  double dist = distanceSP(s, c.p) - c.r;
  if (equal(dist, 0.0))
    return 1;
  if (dist < 0.0)
    return 2;
  return 0;
}

int intersect(const Circle &c1, const Circle &c2) {
  // ???????????° (0 ~ 2) ?????????
  double dist = abs(c1.p - c2.p) - (c1.r + c2.r);
  if (equal(dist, 0.0))
    return 1;
  if (dist < 0.0)
    return 2;
  return 0;
}

// ??????

Point crossPoint(const Segment &s1, const Segment &s2) {
  Vector base = s2.p2 - s2.p1;
  double d1 = abs(cross(base, s1.p1 - s2.p1));
  double d2 = abs(cross(base, s1.p2 - s2.p1));

  // !! ????????´?????¶????????????????????\\????????¨ 0 ?????? !!
  assert(!equal(d1 + d2, 0.0));

  double t = d1 / (d1 + d2);
  return s1.p1 + (s1.p2 - s1.p1) * t;
}

vector<Point> crossPoints(const Circle &c, const Line &l) {
  vector<Point> res;
  if (!intersect(c, l))
    return res;

  Vector pr = project(l, c.p);
  Vector e = (l.p2 - l.p1) / abs(l.p2 - l.p1);
  double base = sqrt(c.r * c.r - norm(pr - c.p));
  res.push_back(pr + e * base);
  res.push_back(pr - e * base);
  if (equalVector(res[0], res[1]))
    res.pop_back();
  return res;
}

vector<Point> crossPoints(const Circle &c1, const Circle &c2) {
  vector<Point> res;
  if (!intersect(c1, c2))
    return res;

  double d = abs(c1.p - c2.p);
  double a = acos(square(c1.r) + square(d) - square(c2.r) / (2 * c2.r * d));
  double t = arg(c2.p - c1.p);
  res.push_back(c1.p + polar(c1.r, t + a));
  res.push_back(c1.p + polar(c1.r, t - a));
  if (equalVector(res[0], res[1]))
    res.pop_back();
}

// ??????

int contains(const Polygon &g, const Point &p) {
  int n = g.size();
  bool res = false;
  for (int i = 0; i < n; i++) {
    Point a = g[i] - p;
    Point b = g[(i + 1) % n] - p;
    if (abs(cross(a, b)) < EPS && dot(a, b) < EPS)
      return ON;
    if (a.imag() > b.imag())
      swap(a, b);
    if (a.imag() < EPS && EPS < b.imag() && cross(a, b) > EPS)
      res = !res;
  }
  return res ? IN : OUT;
}

// ??????

Polygon convexHull(vector<Point> s) {
  Polygon u, l;
  if (s.size() < 3)
    return s;
  sort(s.begin(), s.end());
  u.push_back(s[0]);
  u.push_back(s[1]);
  l.push_back(s[s.size() - 1]);
  l.push_back(s[s.size() - 2]);

  for (int i = 2; i < s.size(); i++) {
    int n = u.size();
    while (n >= 2 && ccw(u[n - 2], u[n - 1], s[i]) != CLOCKWISE) {
      u.pop_back();
      n--;
    }
    u.push_back(s[i]);
  }

  for (int i = s.size() - 3; i >= 0; i--) {
    int n = l.size();
    while (n >= 2 && ccw(l[n - 2], l[n - 1], s[i]) != CLOCKWISE) {
      l.pop_back();
      n--;
    }
    l.push_back(s[i]);
  }

  reverse(l.begin(), l.end());
  for (int i = u.size() - 2; i >= 1; i--) {
    l.push_back(u[i]);
  }

  return l;
}

// ???????§???¢??????

Polygon convexCut(const Polygon &g, const Line &l) {
  Polygon res;
  for (int i = 0; i < g.size(); i++) {
    const Point &a = curr(g, i);
    const Point &b = next(g, i);
    if (ccw(l.p1, l.p2, a) != CLOCKWISE) {
      res.push_back(a);
    }
    if (ccw(l.p1, l.p2, a) * ccw(l.p1, l.p2, b) < 0) {
      res.push_back(crossPoint(Line(a, b), l));
    }
  }

  return res;
}
} // namespace geometry

namespace std {
bool operator<(const geometry::Point &a, const geometry::Point &b) {
  return geometry::cmpx(a, b);
}
} // namespace std

using namespace geometry;

bool intersect(const Polygon &g, const Polygon &h) {
  for (int i = 0; i < g.size(); i++) {
    for (int j = 0; j < h.size(); j++) {
      Segment u(curr(g, i), next(g, i));
      Segment v(curr(h, j), next(h, j));
      // if (intersect(u, v)) return true;
      if (distance(u, v) < EPS)
        return true;
    }
  }

  for (int i = 0; i < g.size(); i++) {
    if (contains(h, g[i]))
      return true;
  }
  for (int i = 0; i < h.size(); i++) {
    if (contains(g, h[i]))
      return true;
  }

  for (int i = 0; i < g.size(); i++) {
    Segment s(curr(g, i), next(g, i));
    for (int j = 0; j < h.size(); j++) {
      if (distanceSP(s, h[j]) < 0.01 + EPS) {
        return true;
      }
    }
  }
  for (int i = 0; i < h.size(); i++) {
    Segment s(curr(h, i), next(h, i));
    for (int j = 0; j < g.size(); j++) {
      if (distanceSP(s, g[j]) < 0.01 + EPS) {
        return true;
      }
    }
  }

  return false;
}

int n;
double d;
Polygon tri[100];
Polygon sqr[100];
vector<int> graph[100];
vector<int> rgraph[100];

void dfs(int v, vector<int> &vs, vector<bool> &used) {
  used[v] = true;
  for (int to : graph[v]) {
    if (!used[to])
      dfs(to, vs, used);
  }
  vs.push_back(v);
}

void rdfs(int v, int k, vector<bool> &used, vector<int> &cmp) {
  used[v] = true;
  cmp[v] = k;
  for (int to : rgraph[v]) {
    if (!used[to])
      rdfs(to, k, used, cmp);
  }
}

vector<vector<int>> scc(vector<int> &cmp) {
  vector<int> vs(0);
  vector<bool> used(n, false);
  cmp.resize(n);

  for (int i = 0; i < n; i++) {
    if (!used[i])
      dfs(i, vs, used);
  }

  used.assign(n, false);

  int k = 0;
  for (int i = vs.size() - 1; i >= 0; i--) {
    if (!used[vs[i]])
      rdfs(vs[i], k++, used, cmp);
  }

  vector<vector<int>> res(k);

  for (int i = 0; i < n; i++) {
    for (int to : graph[i]) {
      if (cmp[i] == cmp[to])
        continue;
      res[cmp[i]].push_back(cmp[to]);
    }
  }

  return res;
}

int solve() {
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < 3; j++) {
      Point &a = curr(tri[i], j);
      Point &b = prev(tri[i], j);
      Point &c = next(tri[i], j);
      if (equal(norm(b - a), norm(c - a))) {
        swap(a, tri[i][2]);
        break;
      }
    }
  }

  for (int i = 0; i < n; i++) {
    sqr[i].resize(4);

    Vector a = tri[i][1] - tri[i][0];
    Vector nv = tri[i][0] + (a / 2.0);
    nv = tri[i][2] - nv;
    nv /= abs(nv);
    nv *= d;

    sqr[i][0] = tri[i][0];
    sqr[i][1] = tri[i][1];
    sqr[i][2] = tri[i][1] + nv;
    sqr[i][3] = tri[i][0] + nv;
  }

  for (int i = 0; i < n; i++) {
    graph[i].clear();
    rgraph[i].clear();
  }

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      if (i == j)
        continue;
      if (intersect(sqr[i], tri[j])) {
        graph[i].push_back(j);
        rgraph[j].push_back(i);
      }
    }
  }

  vector<int> cmp;
  vector<vector<int>> sccgraph = scc(cmp);

  vector<int> indeg(sccgraph.size(), 0);
  for (int i = 0; i < sccgraph.size(); i++) {
    for (int to : sccgraph[i]) {
      indeg[to]++;
    }
  }

  int res = 0;

  for (int i = 0; i < sccgraph.size(); i++) {
    if (indeg[i] == 0) {
      res++;
    }
  }

  return res;
}

int main() {
  while (cin >> n >> d, n) {
    for (int i = 0; i < 100; i++) {
      tri[i].resize(3);
      sqr[i].resize(4);
      graph[i].clear();
      rgraph[i].clear();
    }

    for (int i = 0; i < n; i++) {
      for (int j = 0; j < 3; j++) {
        cin >> tri[i][j];
      }
    }

    cout << solve() << endl;
  }

  return 0;
}