Problem:
最後の扉
秘境の地"ナラマンダ地方"
この奥深い洞窟に眠る黄金の伝説を求め、探検家ボブとマイクは様々な困難に立ち向かいました。ようやくたどり着いた最後の扉。この先には夢に見た黄金が待っています。
その扉には多数の三角形が描かれていました。試しにマイクがその 1 つに触れてみると、その三角形は光を放ちました。光は三角形の底辺から垂直に頂点方向へ長方形を描きながら伸びていき、その先にある別の三角形に触れました。すると、光に触れた三角形も同じように光を放ち、それを繰り返していきました。
扉の三角形は全て二等辺三角形(正三角形は含まない)で、どれも同じ大きさで、どれも重ならず（かつ触れることなく）、またどれも光は一定の距離だけ伸びていました。最後の三角形が光り終えると、そこには何事もなかったかのような静けさが戻ってきました。
ボブは自分の足下に奇妙なメッセージを見つけました。
「むやみに触れるべからず。汝正しくこの扉に触れたとき、この扉は放たれん。  」
ボブとマイクはこのメッセージの意味を考えながら、  何度も三角形に触れてみましたがなかなか扉は開きません。 しかし、それを繰り返していくうちに、二人はメッセージの意味がだんだん分かってきました。
「"むやみに触れるべからず"とは、扉に触れる回数は最小ということ。
できるだけ少ない回数で触れて、全ての三角形を光らせれば、きっと扉は開くはずだ!」
例えば、扉には図 1 のように複数の二等辺三角形が描かれています。
図 1
最初に左下の三角形に触れると、図 2 に示すように、その三角形の底辺から垂直に頂点方向へ光が放たれ、その光が触れる三角形が次々に光ります。
図 2
次に左端の三角形に触れると、図 3 に示すように、全ての三角形が光ります。この手順が全ての三角形を光らせるための最少の手数(2 手)となります。
図 3
さあ、ボブとマイクが最後の扉を開ける手助けをしよう。
扉に描かれている三角形の個数、光の伸びる長さ、それぞれの三角形の頂点の座標を入力とし、全ての三角形を光らせるために扉に触れる最少の回数を出力するプログラムを作成して下さい。光の伸びる長さは、底辺からの長さであるものとします。また、光はそれを放つ三角形の頂点を含むような十分な長さを持ちます。
なお、この問題を解くにあたっては、2 点の距離が 0.01 以下の場合には、同一の点と処理します。また、1 点とひとつの直線の距離が 0.01 以下の場合には、この点はこの直線上にあるとして処理します。
Input
複数のデータセットの並びが入力として与えらる。入力の終わりはゼロふたつの行で示される。各データセットは以下の形式で与えらる。
n
d
T
1
T
2
:
T
n
１行目に扉に描かれている三角形の個数
n
(1 ≤
n
≤ 100) と光の伸びる長さを表す整数
d
(1 ≤
d
≤ 1000) が与えられる。
続く
n
行に各三角形の情報
T
i
が以下の形式で与えられる。
x1
y1
x2
y2
x3
y3
三角形の３つの頂点の座標が整数で与えられる(-1000 ≤
x1
,
y1
,
x2
,
y2
,
x3
,
y3
≤ 1000)。
データセットの数は 20 を超えない。
Output
データセットごとに、扉に触れる最少の回数を1行に出力する。
Sample Input
3 4
1 0 3 0 2 1
2 3 2 5 3 4
5 3 5 5 6 4
3 2
1 0 3 0 2 1
2 3 2 5 3 4
5 3 5 5 6 4
0 0
Output for the Sample Input
1
3

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
  
using namespace std;
  
#define rep(i,n) REP(i,0,n)
#define REP(i,s,e) for(int i=(s); i<(int)(e); i++)
#define pb push_back
#define all(r) (r).begin(),(r).end()
#define rall(r) (r).rbegin(),(r).rend()
#define fi first
#define se second
  
typedef long long ll;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
 
const double EPS = 0.01;
const double INF = 1e12;
const double PI = acos(-1);
typedef complex<double> P;
typedef complex<double> point;
namespace std {
	bool operator < (const P& a, const P& b) {
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}
}
double cross(const P& a, const P& b) {
	return imag(conj(a)*b);
}
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;
typedef vector<P> polygon;

int ccw(P a, P b, P c) {
	b -= a; c -= a;
	if (cross(b, c) > 0)   return +1;       // counter clockwise
	if (cross(b, c) < 0)   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;
}
bool intersectSP(const L &s, const P &p) {
	return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
bool intersectSS(const L &s, const L &t) {
	return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
			ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
enum { OUT, ON, IN };
// int contains(const polygon& P, const point& p) {
// 	bool in = false;
// 	for (int i = 0; i < P.size(); ++i) {
// 		point a = curr(P,i) - p, b = next(P,i) - p;
// 		if (imag(a) > imag(b)) swap(a, b);
// 		if (imag(a) <= 0 && 0 < imag(b))
// 			if (cross(a, b) < 0) in = !in;
// 		if (cross(a, b) == 0 && dot(a, b) <= 0) return ON;
// 	}
// 	return in ? IN : OUT;
// }
int contains(const G& pol, const P& p){
	if(pol.size() < 2) return OUT;
	if(intersectSP({pol[0], pol[1]}, p)) return ON;
	bool f = cross(pol[1]-pol[0], p - pol[0]) > 0;
	for(int i = 1; i < pol.size(); i++) {
		auto& now = pol[i];
		auto& nxt = pol[(i+1) % pol.size()];
		if(intersectSP({nxt, now}, p)) return ON;
		if(f^(cross(nxt-now, p-now)>0)) return OUT;
	}
	return IN;
}


//????????´???????£???????????????????(??????????????£???????????????)
enum{NO_HIT=0, HIT, A_IN_B, B_IN_A};
int HitPol_Pol(const polygon& a, const polygon& b){
	bool f = true, hit = false;
	rep(i, a.size()){
		if(contains(b, a[i]) == OUT) f = false;
		else hit = true;
	}
	if(f) return A_IN_B;
	f = true;
	rep(i, b.size()){
		if(contains(a, b[i]) == OUT) f = false;
		else hit = true;
	}
	if(f) return B_IN_A;
	if(hit) return HIT;
	rep(i, a.size()) rep(j, b.size()){
		L la(curr(a, i), next(a, i)), lb(curr(b, j), next(b, j));
		if(intersectSS(la, lb)) return HIT;
	}
	return NO_HIT;
}
//point???theta???????????¢
point spinP(const point& p, double theta){
	return p*complex<double>(cos(theta),sin(theta));
}
point spinPExtend(const point& p, double theta, double rate){
	return p*complex<double>(rate*cos(theta),rate*sin(theta));
}

struct SCC{//O(V+E)
    static const int MAX_V = 1010;
    int V;
    vector<int> G[MAX_V], rG[MAX_V];
    vector<int> vs;
    bool used[MAX_V];
    int cmp[MAX_V];
    vector<vector<int> > res;
 
 
    SCC(int v) : V(v){};
    void add_edge(int from, int to){
        G[from].push_back(to);
        rG[to].push_back(from);
    }
 
    void dfs(int v){
        used[v] = true;
        for(int i = 0; i < G[v].size(); i++){
            if(!used[G[v][i]]) dfs(G[v][i]);
        }
        vs.push_back(v);
    }
    void rdfs(int v, int k){
        used[v] = true;
        cmp[v] = k;
        for(int i = 0; i < rG[v].size(); i++){
            if(!used[rG[v][i]]) rdfs(rG[v][i], k);
        }
    }
 
    int scc(){
        memset(used, 0, sizeof(used));
        vs.clear();
        for(int v = 0; v < V; v++){
            if(!used[v]) dfs(v);
        }
        memset(used, 0, sizeof(used));
        int k = 0;
        for(int i = vs.size() - 1; i >= 0; i--){
            if(!used[vs[i]]) rdfs(vs[i], k++);
        }
 
        res.clear();
        res.resize(k);
        for(int i = 0; i < V; i++){
            res[cmp[i]].push_back(i);
        }
        return k;
    }
};

int main(){
	int n, d;
	while(cin >> n >> d && (n+d)){
		vector<polygon> tri(n);
		rep(i, n){
			double x, y;
			rep(j, 3){
				cin >> x >> y;
				tri[i].pb({x, y});
			}
		}
		vector<polygon> pol(n);
		rep(i, n){
			double dist[3];
			rep(j, 3){
				dist[j] = abs(curr(tri[i], j)-next(tri[i], j));
			}
			rep(j, 3) {
				if(abs(dist[j] - dist[(j+1)%3])<1e-8){
					pol[i].pb(tri[i][j]);
					pol[i].pb(tri[i][(j+2)%3]);
					pol[i].pb(spinPExtend(pol[i][0]-pol[i][1], (ccw(pol[i][1], pol[i][0], tri[i][(j+1)%3])> 0)?PI/2:-PI/2, d/abs(pol[i][1]-pol[i][0]))+pol[i][1]);
					pol[i].pb(pol[i][2]+pol[i][0]-pol[i][1]);
					break;
				}
			}
		}
		SCC scc(n);
		rep(i, n) rep(j, i){
			if(HitPol_Pol(pol[i], tri[j])!=NO_HIT) scc.add_edge(i, j);
			if(HitPol_Pol(tri[i], pol[j])!=NO_HIT) scc.add_edge(j, i);
		}
		scc.scc();
		vector<int> f(scc.res.size(), 1);
		rep(i, n) rep(j, i){
			if(scc.cmp[i] == scc.cmp[j]) continue;
			if(HitPol_Pol(pol[i], tri[j])!=NO_HIT) f[scc.cmp[j]] = 0;
			else if(HitPol_Pol(tri[i], pol[j])!=NO_HIT) f[scc.cmp[i]] = 0;
		}
		cout<<accumulate(all(f), 0)<<endl;
	}
}
accuracy: 1
time_ms: 70
memory_kb: 3564
final_rank: 20

code_snippet: #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();
	}
}

// ??´???
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;
	}
}

// ???
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;
	}
}

// ????§???¢
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;
}
}


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;
	}
}
accuracy: 1
time_ms: 30
memory_kb: 1356
final_rank: 15

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

struct coor {
	double x, y;
};
struct tri {
	coor p[3];
	coor rec[4];
};

int n, d;
vector<tri> v;
vector<vector<int> > edge;

const double EPS = 1e-9;
const double ERR = 1e-2;

template<class T>
T sqr(T x) {
	return x * x;
}

double dist(coor a, coor b) {
	return sqrt(sqr(a.x-b.x) + sqr(a.y-b.y));
}

double dist_lp(coor c, coor a, coor b) {
	coor v0, v1;
	v0.x = b.x - a.x; v0.y = b.y - a.y;
	v1.x = c.x - a.x; v1.y = c.y - a.y;

	if(sqr(dist(a,b)) + sqr(dist(a,c)) - sqr(dist(c,b)) > 0
			&& sqr(dist(a,b)) + sqr(dist(b,c)) - sqr(dist(c,a)) > 0) {
		double cross;
		cross = fabs(v0.x * v1.y - v0.y * v1.x);
		return cross / dist(a,b);
	}

	return min(dist(a,c), dist(b,c));
}

bool in_poly(coor p, coor poly[], int sz) {
	double sign = +0.0;
	for(int i = 0; i < sz; i++) {
		coor v0, v1;
		v0.x = poly[i].x - p.x; v0.y = poly[i].y - p.y;
		v1.x = poly[(i+1)%sz].x - p.x; v1.y = poly[(i+1)%sz].y - p.y;;

		if(i != 0 && sign * (v0.x * v1.y - v0.y * v1.x) < EPS*EPS) {
			break;
		}
		
		sign = (v0.x * v1.y - v0.y * v1.x);

		if(i == sz-1) {
			return true;
		}
	}

	for(int i = 0; i < sz; i++) {
		if(dist_lp(p,poly[i], poly[(i+1)%sz]) <= ERR + EPS) {
			return true;
		}
	}

	return false;
}

bool seg_cross(coor a, coor b, coor c, coor d) {
	coor v0, v1, v2;
	
	v0.x = a.x - c.x; v0.y = a.y - c.y;
	v1.x = b.x - c.x; v1.y = b.y - c.y;
	v2.x = d.x - c.x; v2.y = d.y - c.y;

	double s, t;
	s = (v0.x * v2.y - v0.y * v2.x) / (v0.x * v1.y - v0.y * v1.x);
	t = - (v1.x * v2.y - v1.y * v2.x) / (v0.x * v1.y - v0.y * v1.x);

	if(s + t > 1-EPS && s > -EPS && t > -EPS) {
		return true;
	}
	return false;
}

bool exist_edge(tri from, tri to) {
	for(int i = 0; i < 3; i++) {
		if(in_poly(to.p[i], from.rec, 4)) {
			return true;
		}
	}
	for(int i = 0; i < 4; i++) {
		if(in_poly(from.rec[i], to.p, 3)) {
			return true;
		}
	}

	for(int i = 0; i < 3; i++) {
		for(int j = 0; j < 4; j++) {
			if(seg_cross(to.p[i], to.p[(i+1)%3], from.rec[j], from.rec[(j+1)%4])) {
				return true;
			}
		}
	}
	return false;
}

bool visited[128];
bool touch[128];
bool path[128];

void check(int i, int s) {
	if(i != s && touch[i])
		touch[i] = false;
	if(path[i])
		return;
	visited[i] = true;
	path[i] = true;
	for(int j = 0; j < (int)edge[i].size(); j++) {
		check(edge[i][j], s);
	}
}

int main() {
	while(cin >> n >> d, n || d) {
		v.clear();
		edge.clear();
		edge.resize(n);
		for(int i = 0; i < n; i++) {
			visited[i] = touch[i] = path[i] = false;
		}
		for(int i = 0; i < n; i++) {
			tri in;
			for(int j = 0; j < 3; j++) {
				coor c;
				cin >> c.x >> c.y;
				in.p[j] = c;
			}

			for(int j = 0; j < 3; j++) {
				if(fabs(dist(in.p[(0+j)%3],in.p[(1+j)%3]) - dist(in.p[(1+j)%3], in.p[(2+j)%3])) < EPS) {
					swap(in.p[(1+j)%3], in.p[1]);
				}
			}

			coor add;
			add.x =	(in.p[1].x - in.p[0].x) + (in.p[1].x - in.p[2].x);
			add.y = (in.p[1].y - in.p[0].y) + (in.p[1].y - in.p[2].y);

			double addlen;
			addlen = sqrt(sqr(add.x) + sqr(add.y));
			add.x = add.x * d / addlen;
			add.y = add.y * d / addlen;

			in.rec[0].x = in.p[0].x; in.rec[0].y = in.p[0].y;
			in.rec[1].x = in.p[2].x; in.rec[1].y = in.p[2].y;
			in.rec[2].x = in.p[2].x + add.x; in.rec[2].y = in.p[2].y + add.y;
			in.rec[3].x = in.p[0].x + add.x; in.rec[3].y = in.p[0].y + add.y;

			v.push_back(in);
		}

		for(int i = 0; i < (int)v.size(); i++) {
			for(int j = 0; j < (int)v.size(); j++) {
				if(i != j) {
					if(exist_edge(v[i], v[j])) {
						edge[i].push_back(j);
					}
				}
			}
		}

		for(int i = 0; i < n; i++) {
			if(!visited[i]) {
				touch[i] = true;
				check(i, i);
			}
			for(int j = 0; j < 128; j++) {
				path[j] = false;
			}
		}

		int res = 0;
		for(int i = 0; i < n; i++) {
			if(touch[i])
				res++;
		}
		cout <<  res << endl;
	}
}
accuracy: 1
time_ms: 20
memory_kb: 1292
final_rank: 11

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

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-10)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): 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 a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

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

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point 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;
}

bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}

double cross3p(Point p,Point q,Point r) { return (r.x-q.x) * (p.y -q.y) - (r.y - q.y) * (p.x - q.x); }
bool collinear(Point p,Point q,Point r) { return fabs(cross3p(p,q,r)) < EPS; }
bool ccwtest(Point p,Point q,Point r){ return cross3p(p,q,r) > 0; }
bool onSegment(Point p,Point q,Point r){
  return collinear(p,q,r) && equals(sqrt(pow(p.x-r.x,2)+pow(p.y-r.y,2)) + sqrt(pow(r.x-q.x,2) + pow(r.y-q.y,2) ),sqrt(pow(p.x-q.x,2)+pow(p.y-q.y,2)) ) ;
}

double angle(Point a,Point b,Point c) {
  double ux = b.x - a.x, uy = b.y - a.y;
  double vx = c.x - a.x, vy = c.y - a.y;
  return acos((ux*vx + uy*vy)/sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)));
}  
  
//多角形poly内（線分上も含む）に点pが存在するかどうは判定する  
bool inPolygon(Polygon poly,Point p){
  if((int)poly.size() == 0)return false;
  rep(i,poly.size()) if(onSegment(poly[i],poly[(i+1)%poly.size()],p))return true;
  double sum = 0;
  for(int i=0; i < (int)poly.size() ;i++) {
    if( equals(cross(poly[i]-p,poly[(i+1)%poly.size()]-p),0.0) ) continue; // ３点が平行だとangleがnanを返しsumがnanになり死ぬ
    if( cross3p(p,poly[i],poly[(i+1)%poly.size()]) < 0 ) sum -= angle(p,poly[i],poly[(i+1)%poly.size()]);
    else                                                 sum += angle(p,poly[i],poly[(i+1)%poly.size()]);
  }
  const double eps = 1e-5;
  return (fabs(sum - 2*M_PI) < eps || fabs(sum + 2*M_PI) < eps);
}  


const int MAX_V = 200;
int V,cmp[MAX_V];
double d;
Point ps[MAX_V][3];
vector<Polygon> poly;
vector<int> G[MAX_V],rG[MAX_V],vs;
bool used[MAX_V];

void add_edge(int s,int t){
  G[s].push_back(t);
  rG[t].push_back(s);
}

void dfs(int v){
  used[v] = true;
  for(int i=0;i<G[v].size();i++) if( !used[G[v][i]] ) dfs(G[v][i]);
  vs.push_back(v);
}

void rdfs(int v,int k){
  used[v] = true;
  cmp[v] = k;
  for(int i=0;i<rG[v].size();i++) if( !used[rG[v][i]] ) rdfs(rG[v][i],k);
}

int scc(){
  rep(i,V) used[i] = false;
  vs.clear();
  rep(v,V) if( !used[v] ) dfs(v);
  rep(i,V) used[i] = false;
  int k = 0;
  for(int i=(int)vs.size()-1;i>=0;i--) if( !used[vs[i]] ) rdfs(vs[i],k++);
  return k;
}


bool check(int a,int b) {
  rep(i,(int)poly[a].size()) {
    Segment seg1 = Segment(poly[a][i],poly[a][(i+1)%poly[a].size()]);
    rep(j,3){
      Segment seg2 = Segment(ps[b][j],ps[b][(j+1)%3]);
      if( equals(cross(seg1.p1-seg1.p2,seg2.p1-seg2.p2),0.0) ) {
        if( onSegment(seg1.p1,seg1.p2,seg2.p1) || onSegment(seg1.p1,seg1.p2,seg2.p2) ||
            onSegment(seg2.p1,seg2.p2,seg1.p1) || onSegment(seg2.p1,seg2.p2,seg1.p2) ) return true;
      } else if( intersectSS(seg1,seg2) ) return true;
    }
  }
  rep(i,3) if( inPolygon(poly[a],ps[b][i]) ) return true;
  return false;
}

void converter(int index){
  Polygon temp;
  rep(i,3) {
    double dist[2] = {abs(ps[index][(i+1)%3]-ps[index][(i+2)%3]),
                      abs(ps[index][(i+2)%3]-ps[index][i])};
    if( equals(dist[0],dist[1]) ) {
      Point p = projection(Line(ps[index][i],ps[index][(i+1)%3]),ps[index][(i+2)%3]);
      Point e = ( ps[index][(i+2)%3] - p ) / abs( ps[index][(i+2)%3] - p );
      temp.push_back(ps[index][i]);
      temp.push_back(ps[index][(i+1)%3]);
      temp.push_back(ps[index][(i+1)%3] + e * d);
      temp.push_back(ps[index][i] + e * d);
      break;
    }
  }
  assert( !temp.empty() );
  poly.push_back(temp);
}

int nV;
struct Edge { int to; };

void draw(vector<vector<Edge> > &nG,int cur){ 
  rep(i,(int)nG[cur].size()){
    if( !used[nG[cur][i].to] ) {
      used[nG[cur][i].to] = true;
      draw(nG,nG[cur][i].to);
    }
  }
}

template<typename T>
bool visit(const T& G,int v,vector<int>& order,vector<int>& color){
  color[v] = 1;
  for(__typeof((G[v]).begin()) e = G[v].begin();e != G[v].end();e++){
      if(color[e->to] == 2)continue;//このvisit以外のvisitで訪れた
      if(color[e->to] == 1)return false;//このvisitで訪れた
      if(!visit(G,e->to,order,color))return false;
    }
  order.push_back(v);
  color[v] = 2;
  return true;
}

template<typename T>
bool topologicalSort(const T& G,vector<int>& order){
  int SizeG = G.size();
  vector<int> color(SizeG); 
  for(int u=0;u<SizeG;u++) if(!color[u] && !visit(G,u,order,color)) return false;
  reverse(order.begin(),order.end());
  return true;
}


void compute(){
  poly.clear(), vs.clear();
  rep(i,V) G[i].clear(), rG[i].clear(), used[i] = false;
  
  rep(i,V) converter(i);

  rep(i,V) rep(j,V) if( i != j && check(i,j) ) add_edge(i,j);

  nV = scc();

  vector<vector<Edge> > nG(nV,vector<Edge>());
  rep(i,V) rep(j,(int)G[i].size()) {
    if( cmp[i] == cmp[G[i][j]] ) continue;
    nG[cmp[i]].push_back((Edge){cmp[G[i][j]]});
  }

  vector<int> order;
  assert( topologicalSort(nG,order) );
  memset(used,false,sizeof(used));
  int answer = 0;
  
  rep(i,nV) if( !used[order[i]] ){
    used[order[i]] = true;
    ++answer;
    draw(nG,order[i]);
  }
  cout << answer << endl;
}

int main(){
  while( cin >> V >> d, (V|(int)d) ){
    rep(i,V) rep(j,3) cin >> ps[i][j].x >> ps[i][j].y;
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1372
final_rank: 12

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

#define REP(i,s,n) for(int i=s;i<n;i++)
#define rep(i,n) REP(i,0,n)
#define EPS (1e-10)
#define equals(a,b) (fabs((a)-(b)) < EPS)
#define COUNTER_CLOCKWISE 1
#define CLOCKWISE -1 
#define ONLINE_BACK 2
#define ONLINE_FRONT -2
#define ON_SEGMENT 0

using namespace std;

class Point{
public:
  double x,y;

  Point(double x = 0,double y = 0): 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 a){return Point(a*x,a*y);}
  Point operator / (double a){return Point(x/a,y/a);}
  Point operator * (Point a){ return Point(x * a.x - y * a.y, x * a.y + y * a.x); }

  bool operator < (const Point& p) const{ return !equals(x,p.x)?x<p.x:(!equals(y,p.y)&&y<p.y); }

  bool operator == (const Point& p)const{ return fabs(x-p.x) < EPS && fabs(y-p.y) < EPS; }

};

struct Segment{
  Point p1,p2;
  Segment(Point p1 = Point(),Point p2 = Point()):p1(p1),p2(p2){}
  bool operator <  (const Segment& s) const { return ( p2 == s.p2 ) ? p1 < s.p1 : p2 < s.p2; }
  bool operator == (const Segment& s) const { return ( s.p1 == p1 && s.p2 == p2 ) || ( s.p1 == p2 && s.p2 == p1 ); }

};

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

ostream& operator << (ostream& os,const Point& a){ os << "(" << a.x << "," << a.y << ")"; }

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

double dot(Point a,Point b){ return a.x*b.x + a.y*b.y; }

double cross(Point a,Point b){ return a.x*b.y - a.y*b.x; }

double norm(Point a){ return a.x*a.x+a.y*a.y; }

double abs(Point a){ return sqrt(norm(a)); }

//rad は角度をラジアンで持たせること
Point rotate(Point a,double rad){ return Point(cos(rad)*a.x - sin(rad)*a.y,sin(rad)*a.x + cos(rad)*a.y); }

// 度をラジアンに変換
double toRad(double agl){ return agl*M_PI/180.0; }

// a => prev, b => cur, c=> next
// prev から cur へ行って next へ行く際の角度を求める
double getArg(Point a,Point b,Point c){
  double arg1 = atan2(b.y-a.y,b.x-a.x);
  double arg2 = atan2(c.y-b.y,c.x-b.x);
  double arg = fabs( arg1 - arg2 );
  while( arg > M_PI ) arg -= 2.0 * M_PI;
  return fabs(arg);
}

int ccw(Point p0,Point p1,Point p2){
  Point a = p1-p0;
  Point 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;
}

bool intersectLL(Line l, Line m) {
  return abs(cross(l.p2-l.p1, m.p2-m.p1)) > EPS || // non-parallel
         abs(cross(l.p2-l.p1, m.p1-l.p1)) < EPS;   // same line
}
bool intersectLS(Line l, Line s) {
  return cross(l.p2-l.p1, s.p1-l.p1)*       // s[0] is left of l
         cross(l.p2-l.p1, s.p2-l.p1) < EPS; // s[1] is right of l
}
bool intersectLP(Line l,Point p) {
  return abs(cross(l.p2-p, l.p1-p)) < EPS;
}
bool intersectSS(Line s, Line t) {
  return ccw(s.p1,s.p2,t.p1)*ccw(s.p1,s.p2,t.p2) <= 0 &&
         ccw(t.p1,t.p2,s.p1)*ccw(t.p1,t.p2,s.p2) <= 0;
}
bool intersectSP(Line s, Point p) {
  return abs(s.p1-p)+abs(s.p2-p)-abs(s.p2-s.p1) < EPS; // triangle inequality
}

Point projection(Line l,Point p) {
  double t = dot(p-l.p1, l.p1-l.p2) / norm(l.p1-l.p2);
  return l.p1 + (l.p1-l.p2)*t;
}
Point reflection(Line l,Point p) {
  return p + (projection(l, p) - p) * 2;
}
double distanceLP(Line l, Point p) {
  return abs(p - projection(l, p));
}
double distanceLL(Line l, Line m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m.p1);
}

double distanceLS(Line l, Line s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}
double distanceSP(Line s, Point p) {
  Point r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s.p1 - p), abs(s.p2 - p));
}

double distanceSS(Line s, Line t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t.p1), distanceSP(s, t.p2)),
             min(distanceSP(t, s.p1), distanceSP(t, s.p2)));
}

Point crosspoint(Line l,Line m){
  double A = cross(l.p2-l.p1,m.p2-m.p1);
  double B = cross(l.p2-l.p1,l.p2-m.p1);
  if(abs(A) < EPS && abs(B) < EPS){
    vector<Point> vec;
    vec.push_back(l.p1),vec.push_back(l.p2),vec.push_back(m.p1),vec.push_back(m.p2);
    sort(vec.begin(),vec.end());
    assert(vec[1] == vec[2]); //同じセグメントかもよ
    return vec[1];
    //return m.p1;
  }
  if(abs(A) < EPS)assert(false);
  return m.p1 + (m.p2-m.p1)*(B/A);
}

//cross product of pq and pr
double cross3p(Point p,Point q,Point r) { return (r.x-q.x) * (p.y -q.y) - (r.y - q.y) * (p.x - q.x); }
  
//returns true if point r is on the same line as the line pq
bool collinear(Point p,Point q,Point r) { return fabs(cross3p(p,q,r)) < EPS; }
  
//returns true if point t is on the left side of line pq
bool ccwtest(Point p,Point q,Point r){
  return cross3p(p,q,r) > 0; //can be modified to accept collinear points
}
 
bool onSegment(Point p,Point q,Point r){
  return collinear(p,q,r) && equals(sqrt(pow(p.x-r.x,2)+pow(p.y-r.y,2)) + sqrt(pow(r.x-q.x,2) + pow(r.y-q.y,2) ),sqrt(pow(p.x-q.x,2)+pow(p.y-q.y,2)) ) ;
}
  
bool isConvex(vector<Point> p) {
  int sz = (int)p.size();
  if(sz < 3)return false;//boundary case, we treat a point or a line as not convex
  bool isLeft = ccwtest(p[0],p[1],p[2]);
  for(int i=1; i<(int)p.size();i++)
    if(ccwtest(p[i],p[(i+1)%sz],p[(i+2)%sz]) != isLeft) return false;
  return true;
}


double angle(Point a,Point b,Point c) {
  double ux = b.x - a.x, uy = b.y - a.y;
  double vx = c.x - a.x, vy = c.y - a.y;
  return acos((ux*vx + uy*vy)/sqrt((ux*ux + uy*uy) * (vx*vx + vy*vy)));
}  
  
//多角形poly内（線分上も含む）に点pが存在するかどうは判定する  
bool inPolygon(Polygon poly,Point p){
  if((int)poly.size() == 0)return false;
  rep(i,poly.size()) if(onSegment(poly[i],poly[(i+1)%poly.size()],p))return true;
  double sum = 0;
  for(int i=0; i < (int)poly.size() ;i++) {
    if( equals(cross(poly[i]-p,poly[(i+1)%poly.size()]-p),0.0) ) continue; // ３点が平行だとangleがnanを返しsumがnanになり死ぬ
    if( cross3p(p,poly[i],poly[(i+1)%poly.size()]) < 0 ) sum -= angle(p,poly[i],poly[(i+1)%poly.size()]);
    else                                                 sum += angle(p,poly[i],poly[(i+1)%poly.size()]);
  }
  // あまり誤差を厳しくしすぎると良くないので以下のほうが良い 
  const double eps = 1e-5;
  return (fabs(sum - 2*M_PI) < eps || fabs(sum + 2*M_PI) < eps);
}  


const int MAX_V = 200;
int V,cmp[MAX_V];
double d;
Point ps[MAX_V][3];
vector<Polygon> poly;
vector<int> G[MAX_V],rG[MAX_V],vs;
bool used[MAX_V];

void add_edge(int s,int t){
  G[s].push_back(t);
  rG[t].push_back(s);
}

void dfs(int v){
  used[v] = true;
  for(int i=0;i<G[v].size();i++) if( !used[G[v][i]] ) dfs(G[v][i]);
  vs.push_back(v);
}

void rdfs(int v,int k){
  used[v] = true;
  cmp[v] = k;
  for(int i=0;i<rG[v].size();i++) if( !used[rG[v][i]] ) rdfs(rG[v][i],k);
}

int scc(){
  rep(i,V) used[i] = false;
  vs.clear();
  rep(v,V) if( !used[v] ) dfs(v);
  rep(i,V) used[i] = false;
  int k = 0;
  for(int i=(int)vs.size()-1;i>=0;i--) if( !used[vs[i]] ) rdfs(vs[i],k++);
  return k;
}


bool check(int a,int b) {
  rep(i,(int)poly[a].size()) {
    Segment seg1 = Segment(poly[a][i],poly[a][(i+1)%poly[a].size()]);
    rep(j,3){
      Segment seg2 = Segment(ps[b][j],ps[b][(j+1)%3]);
      if( equals(cross(seg1.p1-seg1.p2,seg2.p1-seg2.p2),0.0) ) {
        if( onSegment(seg1.p1,seg1.p2,seg2.p1) || onSegment(seg1.p1,seg1.p2,seg2.p2) ||
            onSegment(seg2.p1,seg2.p2,seg1.p1) || onSegment(seg2.p1,seg2.p2,seg1.p2) ) return true;
      } else if( intersectSS(seg1,seg2) ) return true;
    }
  }
  rep(i,3) if( inPolygon(poly[a],ps[b][i]) ) return true;
  return false;
}

void converter(int index){
  Polygon temp;
  rep(i,3) {
    double dist[2] = {abs(ps[index][(i+1)%3]-ps[index][(i+2)%3]),
                      abs(ps[index][(i+2)%3]-ps[index][i])};
    if( equals(dist[0],dist[1]) ) {
      Point p = projection(Line(ps[index][i],ps[index][(i+1)%3]),ps[index][(i+2)%3]);
      Point e = ( ps[index][(i+2)%3] - p ) / abs( ps[index][(i+2)%3] - p );
      temp.push_back(ps[index][i]);
      temp.push_back(ps[index][(i+1)%3]);
      temp.push_back(ps[index][(i+1)%3] + e * d);
      temp.push_back(ps[index][i] + e * d);
      break;
    }
  }
  assert( !temp.empty() );
  poly.push_back(temp);
}

int nV;
struct Edge { int to; };

void draw(vector<vector<Edge> > &nG,int cur){ 
  rep(i,(int)nG[cur].size()){
    if( !used[nG[cur][i].to] ) {
      used[nG[cur][i].to] = true;
      draw(nG,nG[cur][i].to);
    }
  }
}

template<typename T>
bool visit(const T& G,int v,vector<int>& order,vector<int>& color){
  color[v] = 1;
  for(__typeof((G[v]).begin()) e = G[v].begin();e != G[v].end();e++){
      if(color[e->to] == 2)continue;//このvisit以外のvisitで訪れた
      if(color[e->to] == 1)return false;//このvisitで訪れた
      if(!visit(G,e->to,order,color))return false;
    }
  order.push_back(v);
  color[v] = 2;
  return true;
}

template<typename T>
bool topologicalSort(const T& G,vector<int>& order){
  int SizeG = G.size();
  vector<int> color(SizeG); 
  for(int u=0;u<SizeG;u++) if(!color[u] && !visit(G,u,order,color)) return false;
  reverse(order.begin(),order.end());
  return true;
}


void compute(){
  poly.clear(), vs.clear();
  rep(i,V) G[i].clear(), rG[i].clear(), used[i] = false;
  
  rep(i,V) converter(i);

  rep(i,V) rep(j,V) if( i != j && check(i,j) ) add_edge(i,j);

  nV = scc();

  vector<vector<Edge> > nG(nV,vector<Edge>());
  rep(i,V) rep(j,(int)G[i].size()) {
    if( cmp[i] == cmp[G[i][j]] ) continue;
    nG[cmp[i]].push_back((Edge){cmp[G[i][j]]});
  }

  vector<int> order;
  assert( topologicalSort(nG,order) );
  memset(used,false,sizeof(used));
  int answer = 0;
  
  rep(i,nV) if( !used[order[i]] ){
    used[order[i]] = true;
    ++answer;
    draw(nG,order[i]);
  }
  cout << answer << endl;
}

int main(){
  while( cin >> V >> d, (V|(int)d) ){
    rep(i,V) rep(j,3) cin >> ps[i][j].x >> ps[i][j].y;
    compute();
  }
  return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 1380
final_rank: 13

code_snippet: #include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
const double EPS = 1e-8;
const double INF = 1e+10;
const double PI = acos(-1);
int sig(double r) { return (r < -EPS) ? -1 : (r > +EPS) ? +1 : 0; }
inline double ABS(double a){return max(a,-a);}
struct Pt {
	double x, y;
	Pt() {}
	Pt(double x, double y) : x(x), y(y) {}
	Pt operator+(const Pt &a) const { return Pt(x + a.x, y + a.y); }
	Pt operator-(const Pt &a) const { return Pt(x - a.x, y - a.y); }
	Pt operator*(const Pt &a) const { return Pt(x * a.x - y * a.y, x * a.y + y * a.x); }
	Pt operator-() const { return Pt(-x, -y); }
	Pt operator*(const double &k) const { return Pt(x * k, y * k); }
	Pt operator/(const double &k) const { return Pt(x / k, y / k); }
	double ABS() const { return sqrt(x * x + y * y); }
	double abs2() const { return x * x + y * y; }
	double arg() const { return atan2(y, x); }
	double dot(const Pt &a) const { return x * a.x + y * a.y; }
	double det(const Pt &a) const { return x * a.y - y * a.x; }
};
double tri(const Pt &a, const Pt &b, const Pt &c) { return (b - a).det(c - a); }
int iSP(Pt a, Pt b, Pt c) {
	int s = sig((b - a).det(c - a));
	if (s) return s;
	if (sig((b - a).dot(c - a)) < 0) return -2; // c-a-b
	if (sig((a - b).dot(c - b)) < 0) return +2; // a-b-c
	return 0;
}
bool iSS(Pt a, Pt b, Pt c, Pt d) {
	return (iSP(a, b, c) * iSP(a, b, d) <= 0 && iSP(c, d, a) * iSP(c, d, b) <= 0);
}
int g[110][110];
Pt p[110][3];
int UF[110];
int v[110];
int FIND(int a){
	if(UF[a]<0)return a;
	return UF[a]=FIND(UF[a]);
}
void UNION(int a,int b){
	a=FIND(a);b=FIND(b);if(a==b)return;UF[a]+=UF[b];UF[b]=a;
}
int main(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++)UF[i]=-1;
		for(int i=0;i<a;i++)for(int j=0;j<a;j++)g[i][j]=0;
		for(int i=0;i<a;i++)g[i][i]=1;
		for(int i=0;i<a;i++){
			double ax,bx,cx,ay,by,cy;
			scanf("%lf%lf%lf%lf%lf%lf",&ax,&ay,&bx,&by,&cx,&cy);
			double A=(bx-cx)*(bx-cx)+(by-cy)*(by-cy);
			double B=(ax-cx)*(ax-cx)+(ay-cy)*(ay-cy);
			double C=(ax-bx)*(ax-bx)+(ay-by)*(ay-by);
			if(ABS(A-B)<EPS){
				p[i][0]=Pt(ax,ay);p[i][1]=Pt(bx,by);p[i][2]=Pt(cx,cy);
			}
			if(ABS(B-C)<EPS){
				p[i][2]=Pt(ax,ay);p[i][0]=Pt(bx,by);p[i][1]=Pt(cx,cy);
			}
			if(ABS(C-A)<EPS){
				p[i][1]=Pt(ax,ay);p[i][2]=Pt(bx,by);p[i][0]=Pt(cx,cy);
			}
		}
		for(int i=0;i<a;i++)if(iSP(p[i][0],p[i][2],p[i][1])==-1)swap(p[i][0],p[i][1]);
		for(int i=0;i<a;i++)for(int j=0;j<a;j++){
			if(i==j)continue;
			Pt t[4];
			t[0]=p[i][0];
			t[1]=p[i][1];
			t[3]=(t[1]-t[0])*Pt(0,-1);
			t[3]=t[0]+t[3]/t[3].ABS()*(double)b;
			t[2]=(t[1]-t[0])*Pt(0,-1);
			t[2]=t[1]+t[2]/t[2].ABS()*(double)b;
		
			bool ok=false;
			for(int k=0;k<3;k++){
				bool L=false;
				bool R=false;
				for(int l=0;l<4;l++){
					if(iSS(t[l],t[(l+1)%4],p[j][k],p[j][k]+(p[j][(k+1)%3]-p[j][k])*1000000.0))L=true;
					if(iSS(t[l],t[(l+1)%4],p[j][(k+1)%3],p[j][(k+1)%3]+(p[j][k]-p[j][(k+1)%3])*1000000.0))R=true;
					if(iSS(t[l],t[(l+1)%4],p[j][k],p[j][(k+1)%3]))ok=true;
				}
				if(L&&R)ok=true;
			}
			for(int l=0;l<4;l++){
				bool L=false;
				bool R=false;
				for(int k=0;k<3;k++){
					if(iSS(t[l],t[l]+(t[(l+1)%4]-t[l])*1000000.0,p[j][k],p[j][(k+1)%3]))L=true;
					if(iSS(t[(l+1)%4],t[(l+1)%4]+(t[l]-t[(l+1)%4])*1000000.0,p[j][k],p[j][(k+1)%3]))R=true;
				}
				if(L&&R)ok=true;
			}
			
			if(ok){
				g[i][j]=1;
			}
		}
		for(int k=0;k<a;k++)for(int i=0;i<a;i++)for(int j=0;j<a;j++)
			g[i][j]|=g[i][k]&g[k][j];
		for(int i=0;i<a;i++)for(int j=0;j<a;j++)if(g[i][j]&&g[j][i])UNION(i,j);
		int ret=0;
		for(int i=0;i<a;i++)v[i]=0;
		for(int i=0;i<a;i++){
			bool ok=true;
			for(int j=0;j<a;j++){
				if(FIND(i)!=FIND(j)&&g[j][i])ok=false;
			}
			if(ok&&!v[FIND(i)]){
				ret++;v[FIND(i)]=1;
			}
		}
		printf("%d\n",ret);
	}
}
accuracy: 1
time_ms: 10
memory_kb: 1116
final_rank: 4

code_snippet: #include<iostream>
#include<vector>
#include<queue>
#include<functional>
#include<cfloat>
#include<tuple>
#include<set>
#include<stack>
#include<algorithm>

const double INF = DBL_MAX / 3.0;

const double EPS = 1e-10;
enum POSITION {ONLINE_FRONT = -2, CLOCKWISE, ON_SEGMENT, COUNTER_CLOCKWISE, ONLINE_BACK};
// class
class Point;
class Segment;
class Line;
class Polygon;
// member
class Point {
double x_value, y_value;
public:
Point() :x_value(0.0), y_value(0.0) {}
Point(double d) :x_value(d), y_value(d) {}
Point(double a, double b) :x_value(a), y_value(b) {}
double x() const {return x_value;}
double y() const {return y_value;}
double x(double d) {return x_value = d;}
double y(double d) {return y_value = d;}
const Point operator-() const;
const Point& operator=(const Point&);
const Point& operator+=(const Point&);
const Point& operator-=(const Point&);
const Point& operator*=(const Point&);
const Point& operator/=(const Point&);
double dot(const Point&) const;
double cross(const Point&) const;
double abs() const;
double norm() const;
const Point normalize() const;
double distance(const Point&) const;
double distance(const Segment&) const;
double distance(const Line&) const;
bool intersect(const Point&) const;
bool intersect(const Segment&) const;
bool intersect(const Line&) const;
const Point projection(const Line&) const;
const Point reflection(const Line&) const;
POSITION ccw(const Point&, const Point&) const;
};
bool operator==(const Point& lhs, const Point& rhs);
bool operator!=(const Point& lhs, const Point& rhs);
bool operator<(const Point& lhs, const Point& rhs);
bool operator>(const Point& lhs, const Point& rhs);
bool operator<=(const Point& lhs, const Point& rhs);
bool operator>=(const Point& lhs, const Point& rhs);
const Point operator+(const Point& lhs, const Point& rhs);
const Point operator-(const Point& lhs, const Point& rhs);
const Point operator*(const Point& lhs, const Point& rhs);
const Point operator/(const Point& lhs, const Point& rhs);
class Segment {
Point source_point, target_point;
public:
Segment(double x1 = 0.0, double y1 = 0.0, double x2 = 0.0, double y2 = 0.0) :source_point(Point(x1, y1)), target_point(Point(x2, y2)) {}
Segment(const Point& a, const Point& b) :source_point(a), target_point(b) {}
const Point& source() const {return source_point;}
const Point& target() const {return target_point;}
const Point& source(const Point& p) {return source_point = p;}
const Point& target(const Point& p) {return target_point = p;}
const Line line() const;
double distance(const Point&) const;
double distance(const Segment&) const;
double distance(const Line&) const;
bool intersect(const Point&) const;
bool intersect(const Segment&) const;
bool intersect(const Line&) const;
POSITION ccw(const Point&) const;
};
class Line {
Point source_point, target_point;
public:
Line(double x1 = 0.0, double y1 = 0.0, double x2 = 0.0, double y2 = 0.0) :source_point(Point(x1, y1)), target_point(Point(x2, y2)) {}
Line(const Point& a, const Point& b) :source_point(a), target_point(b) {}
const Point& source() const {return source_point;}
const Point& target() const {return target_point;}
const Point& source(const Point& p) {return source_point = p;}
const Point& target(const Point& p) {return target_point = p;}
const Segment segment() const;
double distance(const Point&) const;
double distance(const Segment&) const;
double distance(const Line&) const;
bool intersect(const Point&) const;
bool intersect(const Segment&) const;
bool intersect(const Line&) const;
const Point projection(const Point&) const;
const Point reflection(const Point&) const;
const Point crosspoint(const Line&) const;
POSITION ccw(const Point&) const;
};
class Polygon {
std::vector<Point> point;
public:
Polygon() {}
explicit Polygon(std::vector<Point> p) :point(p) {}
const std::vector<Point>& vertex() const {return point;}
const Point& vertex(int i) const {return point.at(i);}
const std::vector<Segment> edge() const {
std::vector<Segment> result;
for(int i = 0; i < size(); ++i) result.push_back(Segment(vertex(i), vertex((i + 1) % size())));
return result;
}
const Segment edge(int i) const {return Segment(vertex(i), vertex((i + 1) % size()));}
int size() const {return point.size();}
void add(const Point&);
double area() const;
bool convex() const;
bool include(const Point&) const;
bool intersect(const Polygon&) const;
bool on_edge(const Point&) const;
const Polygon convex_hull() const;
};
// Point
bool operator==(const Point& lhs, const Point& rhs) {return lhs.x() == rhs.x() && lhs.y() == rhs.y();}
bool operator!=(const Point& lhs, const Point& rhs) {return lhs.x() != rhs.x() || lhs.y() != rhs.y();}
bool operator<(const Point& lhs, const Point& rhs) {return lhs.x() != rhs.x() ? lhs.x() < rhs.x() : lhs.y() < rhs.y();}
bool operator>(const Point& lhs, const Point& rhs) {return lhs.x() != rhs.x() ? lhs.x() > rhs.x() : lhs.y() > rhs.y();}
bool operator<=(const Point& lhs, const Point& rhs) {return lhs.x() != rhs.x() ? lhs.x() < rhs.x() : lhs.y() <= rhs.y();}
bool operator>=(const Point& lhs, const Point& rhs) {return lhs.x() != rhs.x() ? lhs.x() > rhs.x() : lhs.y() >= rhs.y();}
const Point operator+(const Point& lhs, const Point& rhs) {return Point(lhs.x() + rhs.x(), lhs.y() + rhs.y());}
const Point operator-(const Point& lhs, const Point& rhs) {return Point(lhs.x() - rhs.x(), lhs.y() - rhs.y());}
const Point operator*(const Point& lhs, const Point& rhs) {return Point(lhs.x() * rhs.x(), lhs.y() * rhs.y());}
const Point operator/(const Point& lhs, const Point& rhs) {return Point(lhs.x() / rhs.x(), lhs.y() / rhs.y());}
const Point Point::operator-() const {return Point(-x(), -y());}
const Point& Point::operator=(const Point& p) {x(p.x()); y(p.y()); return *this;}
const Point& Point::operator+=(const Point& p) {return *this = *this + p;}
const Point& Point::operator-=(const Point& p) {return *this = *this - p;}
const Point& Point::operator*=(const Point& p) {return *this = *this * p;}
const Point& Point::operator/=(const Point& p) {return *this = *this / p;}
double Point::dot(const Point& p) const {return x() * p.x() + y() * p.y();}
double Point::cross(const Point& p) const {return x() * p.y() - y() * p.x();}
double Point::abs() const {return hypot(x(), y());}
double Point::norm() const {return x() * x() + y() * y();}
const Point Point::normalize() const {return abs() == 0.0 ? Point(0.0, 0.0) : Point(x(), y()) / abs();}
double Point::distance(const Point& p) const {return (p - (*this)).abs();}
double Point::distance(const Segment& s) const {return s.distance(*this);}
double Point::distance(const Line& l) const {return l.distance(*this);}
bool Point::intersect(const Point& p) const {return *this == p;}
bool Point::intersect(const Segment& s) const {return s.intersect(*this);}
bool Point::intersect(const Line& l) const {return l.intersect(*this);}
const Point Point::projection(const Line& l) const {return l.projection(*this);}
const Point Point::reflection(const Line& l) const {return l.reflection(*this);}
POSITION Point::ccw(const Point& b, const Point& p) const {
const Point& a = *this;
Point v1 = b - a;
Point v2 = p - a;
if(v1.cross(v2) > EPS) return COUNTER_CLOCKWISE;
if(v1.cross(v2) < -EPS) return CLOCKWISE;
if(v1.dot(v2) < -EPS) return ONLINE_BACK;
if(v2.norm() - v1.norm() > EPS) return ONLINE_FRONT;
return ON_SEGMENT;
}
// Segment
const Line Segment::line() const {return Line(source(), target());}
double Segment::distance(const Point& p) const {
Point q = line().projection(p);
if(intersect(q)) return q.distance(p);
return std::min(source().distance(p), target().distance(p));
}
double Segment::distance(const Segment& s) const {
if(intersect(s)) return 0.0;
double a = distance(s.source());
double b = distance(s.target());
double c = s.distance(source());
double d = s.distance(target());
return std::min({a, b, c, d});
}
double Segment::distance(const Line& l) const {return l.distance(*this);}
bool Segment::intersect(const Point& p) const {return source().distance(p) + target().distance(p) - target().distance(source()) <= EPS;}
bool Segment::intersect(const Segment& s) const {
bool a = ccw(s.source()) * ccw(s.target()) <= 0;
bool b = s.ccw(source()) * s.ccw(target()) <= 0;
return a && b;
}
bool Segment::intersect(const Line& l) const {return l.intersect(*this);}
POSITION Segment::ccw(const Point& p) const {return source().ccw(target(), p);}
// Line
const Segment Line::segment() const {return Segment(source(), target());}
double Line::distance(const Point& p) const {return p.distance(projection(p));}
double Line::distance(const Segment& s) const {
if(intersect(s)) return 0.0;
double a = distance(s.source());
double b = distance(s.target());
return a < b ? a : b;
}
double Line::distance(const Line& l) const {return intersect(l) ? 0.0 : distance(l.source());}
bool Line::intersect(const Point& p) const {
Point v1 = source() - p;
Point v2 = target() - p;
return fabs(v2.cross(v1)) < EPS;
}
bool Line::intersect(const Segment& s) const {
Point v1 = target() - source();
Point v2 = s.source() - source();
Point v3 = s.target() - source();
return v1.cross(v2) * v1.cross(v3) <= EPS;
}
bool Line::intersect(const Line& l) const {
Point v1 = target() - source();
Point v2 = l.target() - l.source();
Point v3 = l.source() - source();
return fabs(v1.cross(v2)) > EPS || fabs(v1.cross(v3)) < EPS;
}
const Point Line::projection(const Point& p) const {
Point v1 = p - source();
Point v2 = source() - target();
return Point(source() + v2 * (v1.dot(v2) / v2.norm()));
}
const Point Line::reflection(const Point& p) const {
return p + (projection(p) - p) * 2.0;
}
const Point Line::crosspoint(const Line& l) const {
Point v1 = target() - source();
Point v2 = l.target() - l.source();
Point v3 = target() - l.source();
double a = v1.cross(v2);
double b = v1.cross(v3);
if(fabs(a) <= EPS && fabs(b) <= EPS) return l.source();
return l.source() + v2 * (b / a);
}
POSITION Line::ccw(const Point& p) const {return source().ccw(target(), p);}
// Polygon
void Polygon::add(const Point& p) {point.push_back(p);}
double Polygon::area() const {
double sum = 0.0;
for(int i = 0; i < size(); ++i) sum += vertex(i).cross(vertex((i+1) % size()));
return fabs(sum) / 2.0;
}
bool Polygon::convex() const {
POSITION direction = ONLINE_BACK;
for(int i = 1; i < size(); ++i) {
POSITION d = vertex(i - 1).ccw(vertex(i), vertex((i + 1) % size()));
if(d != CLOCKWISE && d != COUNTER_CLOCKWISE) continue;
if(direction == ONLINE_BACK) direction = d;
if(direction != d) return false;
}
return true;
}
bool Polygon::include(const Point& p) const {
bool in = false;
for(int i = 0; i < size(); ++i) {
Point a = vertex(i) - p;
Point b = vertex((i + 1) % size()) - p;
if(a.y() > b.y()) std::swap(a, b);
if(a.y() <= 0.0 && 0 < b.y() && a.cross(b) < 0.0) in = !in;
if(fabs(a.cross(b)) <= EPS && a.dot(b) <= EPS) return true;
}
return in;
}
bool Polygon::intersect(const Polygon& p) const {
for(const auto& e1: edge()) for(const auto& e2: p.edge()) if(e1.intersect(e2)) return true;
return false;
}
bool Polygon::on_edge(const Point& p) const {
for(int i = 0; i < size(); ++i) if(vertex(i).ccw(vertex((i + 1) % size()), p) == ON_SEGMENT) return true;
return false;
}
const Polygon Polygon::convex_hull() const {                // Andrew's Monotone Chain
Polygon result;
std::vector<Point> res;
std::vector<Point> original = vertex();
sort(original.begin(), original.end());
original.insert(original.end(), original.rbegin() + 1, original.rend());
for(const auto& v: original) {
while(res.size() >= 2 && res[res.size() - 2].ccw(res[res.size() - 1], v) == CLOCKWISE) res.pop_back();
res.push_back(v);
}
res.pop_back();
for(const auto& v: res) result.add(v);
return result;
}

// Edge
class Edge {
int from_value, to_value;
double weight_value;
public:
Edge() {}
Edge(int f, int t, double w) :from_value(f), to_value(t), weight_value(w) {}
int from() const {return from_value;}
int to() const {return to_value;}
double weight() const {return weight_value;}
};

// Graph
class Graph {
int size_value;
std::vector<std::vector<Edge>> edge_value;

public:
explicit Graph(int s) :size_value(s) {edge_value.resize(s);}

int size() const {return size_value;}
const std::vector<Edge>& edge(int v) const {return edge_value[v];}

void add(const Edge& e);
void add(int from, int to, double weight);
public:
std::vector<std::vector<int>> Kosaraju() const;
private:
void Kosaraju_dfs_postorder(int from, std::vector<bool>& visited, std::stack<int>& order) const;
std::vector<int> Kosaraju_dfs_decompose(const std::vector<std::vector<Edge>>& reverse_edge, int from, std::vector<bool>& visited) const;
};

// implements
void Graph::add(const Edge& e) {edge_value[e.from()].push_back(e);}
void Graph::add(int from, int to, double weight) {edge_value[from].push_back(Edge(from, to, weight));}
std::vector<std::vector<int>> Graph::Kosaraju() const {
std::vector<std::vector<int>> result;
std::vector<bool> visited(size(), false);
std::stack<int> order;
for(int v = 0; v < size(); ++v) if(!visited[v]) Kosaraju_dfs_postorder(v, visited, order);
std::vector<std::vector<Edge>> reverse_edge(size(), std::vector<Edge>());
for(int v = 0; v < size(); ++v) for(const auto& e: edge(v)) reverse_edge[e.to()].push_back(Edge(e.to(), e.from(), e.weight()));
visited = std::vector<bool>(size(), false);
while(!order.empty()) {
int v = order.top();
order.pop();
if(visited[v]) continue;
result.push_back(Kosaraju_dfs_decompose(reverse_edge, v, visited));
}
return result;
}
void Graph::Kosaraju_dfs_postorder(int from, std::vector<bool>& visited, std::stack<int>& order) const {
visited[from] = true;
for(const auto& e: edge(from)) if(!visited[e.to()]) Kosaraju_dfs_postorder(e.to(), visited, order);
order.push(from);
}
std::vector<int> Graph::Kosaraju_dfs_decompose(const std::vector<std::vector<Edge>>& reverse_edge, int from, std::vector<bool>& visited) const {
std::vector<int> result;
result.push_back(from);
visited[from] = true;
for(const auto& e: reverse_edge[from]) {
if(visited[e.to()]) continue;
std::vector<int> add = Kosaraju_dfs_decompose(reverse_edge, e.to(), visited);
result.insert(result.end(), add.begin(), add.end());
}
return result;
}

using namespace std; 
int main() {
int n, d;
while(cin >> n >> d, n | d) {
vector<Polygon> triangle(n);
for(auto &t: triangle) {
vector<Point> vertex(3);
for(auto &v: vertex) {
double x, y;
cin >> x >> y;
v = Point(x, y);
}
if(vertex[0].distance(vertex[1]) == vertex[0].distance(vertex[2])) swap(vertex[0], vertex[2]);
if(vertex[1].distance(vertex[0]) == vertex[1].distance(vertex[2])) swap(vertex[1], vertex[2]);
for(const auto &v: vertex) t.add(v);
}

vector<Polygon> light(n);
for(int i = 0; i < triangle.size(); ++i) {
Point n = (triangle[i].vertex(1) - triangle[i].vertex(0)).normalize();
if(triangle[i].vertex(0).ccw(triangle[i].vertex(1), triangle[i].vertex(2)) > 0) n = Point(-n.y(), n.x());
else                                                                            n = Point(n.y(), -n.x());
light[i].add(triangle[i].vertex(0));
light[i].add(triangle[i].vertex(0) + (n * d));
light[i].add(triangle[i].vertex(1) + (n * d));
light[i].add(triangle[i].vertex(1));
}

Graph g(n);
for(int i = 0; i < n; ++i) {
for(int j = 0; j < n; ++j) {
if(i == j) continue;
bool shine = false;

// 辺の交差判定
for(const auto &l: light[i].edge())
for(const auto &t: triangle[j].edge())
if(l.intersect(t)) shine = true;
// 点の包含判定
for(const auto &v: light[i].vertex())
if(triangle[j].include(v)) shine = true;
for(const auto &v: triangle[j].vertex())
if(light[i].include(v)) shine = true;
// 線分と点の距離が0.01以下
for(const auto &l: light[i].edge())
for(const auto &t: triangle[j].edge())
if(l.distance(t) <= 0.01) shine = true;

if(!shine) continue;
g.add(Edge(i, j, 1));
}
}

auto scc = g.Kosaraju();
vector<int> indegree(scc.size(), 0);
for(int i = 0; i < scc.size(); ++i) {
for(int j = i + 1; j < scc.size(); ++j) {
for(const auto& v: scc[i]) for(const auto& e: g.edge(v)){
if(find(scc[j].begin(), scc[j].end(), e.to()) != scc[j].end()) ++indegree[j];
}
}
}
cout << count(indegree.begin(), indegree.end(), 0) << endl;
}
}
accuracy: 1
time_ms: 80
memory_kb: 1320
final_rank: 18

code_snippet: #include<iostream>
#include<vector>
#include<cfloat>
#include<cassert>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;
#define rep(i, n) for ( int i = 0; i < (int)n; i++)
#define EPS 0.01
#define equals(a, b) (fabs((a) - (b)) <= EPS )
#define dle(a, b) (equals(a, b) || a < b )

#define MAX 100

class Point{
    public:
    double x, y;
    Point ( double x = 0, double y = 0): 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 a ){ return Point(x*a, y*a); }
    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 abs() { return sqrt(norm());}
    double norm() { return x*x + y*y; }
};
typedef Point Vector;
typedef vector<Point> Polygon;

double norm( Vector a ){ return a.x*a.x + a.y*a.y; }
double abs( Vector a ) { return sqrt(norm(a)); }
double dot( Vector a, Vector b ){ return a.x*b.x + a.y*b.y; }
double cross( Vector a, Vector b ){ return a.x*b.y - a.y*b.x; }
static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw( Point p0, Point p1, 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;
}
bool isIntersect(Point p1, Point p2, Point p3, Point p4){
    return ( ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
	     ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0 );
}

bool isInside(Polygon gon, Point p ){
    for ( int i = 0; i < gon.size(); i++ ){
	if ( ccw(gon[i], gon[(i+1)%gon.size()], p) == CLOCKWISE ) return false;
    }
    return true;
}

class Triangle{
    public:
    vector<Point> P;
    Triangle(){ P.resize(3);}
    void normalize(){
	vector<Point> tmp(3);
	if ( equals(norm(P[0]-P[1]), norm(P[0]-P[2])) ){
	    tmp[0] = P[1]; tmp[1] = P[2]; tmp[2] = P[0];
	} else if ( equals(norm(P[1]-P[0]), norm(P[1]-P[2])) ){
	    tmp[0] = P[0]; tmp[1] = P[2]; tmp[2] = P[1];
	} else if ( equals(norm(P[2]-P[0]), norm(P[2]-P[1])) ){
	    tmp[0] = P[0]; tmp[1] = P[1]; tmp[2] = P[2];
	}
	P = tmp;
	if ( ccw(P[0], P[1], P[2]) != COUNTER_CLOCKWISE ) swap(P[0], P[1]);
    }

    double getArea(){
	double a = abs(P[0]-P[1]); 
	double b = abs(P[0]-P[2]); 
	double c = abs(P[2]-P[1]); 
	double s= (a + b + c)/2.0;
	return sqrt(s*(s-a)*(s-b)*(s-c));
    }
};

class Graph{
public:
    int n;
    vector<vector<int> > adj;
    Graph(int n = 0):n(n){
	adj.resize(n);
	rep(i, n) adj[i].clear();
    }
    void connect(int i, int j){ adj[i].push_back(j); }
    void transpose(){
	vector<vector<int> > nadj;
	nadj.resize(n);
	rep(i, n) nadj[i].clear();
	rep(i, n) rep(j, adj[i].size())	nadj[adj[i][j]].push_back(i);
	rep(i, n) adj[i] = nadj[i];
    }
};

int n;
double d;
Triangle T[MAX];

Graph g;
int visited[MAX], finish[MAX], t;
vector<int> com;

bool overlapPolygon(Polygon p1, Polygon p2){
    rep(i, p1.size()) if ( isInside(p2, p1[i]) ) return true;
    rep(i, p2.size()) if ( isInside(p1, p2[i]) ) return true;
    rep(i, p1.size()) rep(j, p2.size()){
      if ( isIntersect(p1[i], p1[(i+1)%p1.size()], p2[j], p2[(j+1)%p2.size()])) return true;
    }
    return false;
}

bool overlap( int t1, int t2){
    Triangle s = T[t1];
    vector<Point> rect, tri;
    Point c = Point((s.P[0].x+s.P[1].x)/2, (s.P[0].y+s.P[1].y)/2);
    Vector v = s.P[2] - c;
    double a = v.abs();
    v.x = d*v.x/a;
    v.y = d*v.y/a;
    Point l = s.P[0] + v;
    Point r = s.P[1] + v;
    rect.push_back(s.P[1]);
    rect.push_back(r);
    rect.push_back(l);
    rect.push_back(s.P[0]);
    tri = T[t2].P;
    return overlapPolygon(rect, tri);
}

void dfs(int &u){
    visited[u] = t++;
    rep(i, g.adj[u].size()){
	int v = g.adj[u][i];
	if ( visited[v] == -1 ) dfs(v);
    }
    finish[u] = t++;
}

void dfsT(int &u){
    com.push_back(u);
    visited[u] = 1;
    rep(i, g.adj[u].size()){
	int v = g.adj[u][i];
	if ( visited[v] == 0 ) dfsT(v);
    }
}

void makeGraph(){
    g = Graph(n);
    rep(i, n) rep(j, n)
	if ( i != j && overlap(i, j) )
	    g.connect(i, j);
}

int scc(){
    int id[MAX];
    bool indeg[MAX];

    rep(i, n) visited[i] = finish[i] = -1;
    t = 0;
    rep(i, n) if ( visited[i] == -1 ) dfs(i);

    g.transpose();
    
    vector<pair<int, int> > order;
    rep(i, n) order.push_back(make_pair(finish[i], i));
    sort(order.begin(), order.end());
    
    rep(i, n) visited[i] = 0;
    
    int ncom = 0;
    
    for ( int i = n-1; i >= 0; i-- ){
	int u = order[i].second;
	com.clear();
	if ( visited[u] == 0 ) {
	    dfsT(u);
	    rep(c, com.size()) id[com[c]] = ncom;
	    ncom++;
	}
    }
    
    int cnt = 0;
    g.transpose();

    rep(i, ncom) indeg[i] = false;
    
    rep(u, n) rep(i, g.adj[u].size()){
	int v = g.adj[u][i];
	if ( id[v] != id[u] ) indeg[id[v]] = true;
    }
    rep(i, ncom) if (!indeg[i]) cnt++;
    
    return cnt;
}

main(){
    while( cin >> n >> d && n ){
	rep(i, n){
	    Triangle t;
	    rep(j, 3) cin >> t.P[j].x >> t.P[j].y;
	    t.normalize();
	    T[i] = t;
	}
	double a = T[0].getArea();

	for ( int i = 0; i < n-1; i++ ){
	    for ( int j = i+1; j < n; j++ ){
		rep(a, 3) rep(b, 3){
		    Point p1 = T[i].P[a];
		    Point p2 = T[i].P[(a+1)%3];
		    Point p3 = T[j].P[b];
		    Point p4 = T[j].P[(b+1)%3];
		}
	    }
	}

	makeGraph();
	cout << scc() << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 1284
final_rank: 8

code_snippet: #include<cstdio>
#include<vector>
#include<complex>
#include<cstring>
#include<algorithm>

#define rep(i,a) for(int i=0;i<a;i++)
#define EQ(a,b) (abs((a)-(b))<EPS)
#define pb push_back
#define fs first
#define sc second
using namespace std;

typedef double D;
typedef complex<D> P;
typedef pair<P,P> L;
typedef vector<P> Poly;

const D EPS = 1e-8;

namespace std{
  bool operator<(const P &a,const P &b){
    return EQ(real(a),real(b))?imag(a)<imag(b):real(a)<real(b);
  }
}

vector<int> g[110];
vector<int> rg[110];
vector<int> vs;
bool use[110];
int ord[110];
int n,d;
Poly tri[110];
Poly rect[110];

inline P unit(P p){return p/abs(p);}
inline D dot(P x,P y){return real(conj(x)*y);}
inline D cross(P x,P y){return imag(conj(x)*y);}

inline vector<P> convex_hull(vector<P> v){
  int n = v.size(), k = 0;
  sort(v.begin(),v.end());
  vector<P> r(2*n);
  for(int i=0;i<n;i++){
    while(k>1 && cross(r[k-1]-r[k-2],v[i]-r[k-1]) <= EPS)k--;
    r[k++] = v[i];
  }
  for(int i=n-2,t=k;i>=0;i--){
    while(k>t && cross(r[k-1]-r[k-2],v[i]-r[k-1]) <= EPS)k--;
    r[k++] = v[i];
  }
  r.resize(k-1);
  return r;
}

inline int ccw(P &a,P b,P c){
  b -= a; c -= a;
  if(cross(b,c)>EPS)return 1;
  if(cross(b,c)<-EPS)return -1;
  if(dot(b,c)<-EPS)return 2;
  if(abs(b)<abs(c))return -2;
  return 0;
}

inline bool is_cp(L a,L b){
  if(ccw(a.fs,a.sc,b.fs)*ccw(a.fs,a.sc,b.sc)<=0)
    if(ccw(b.fs,b.sc,a.fs)*ccw(b.fs,b.sc,a.sc)<=0)return true;
  return false;
}

inline bool inter_pos(Poly &p,P &x){
  int s = p.size();
  if(!s)return false;
  rep(i,s)if(ccw(p[i],p[(i+1)%s],x)==-1)return false;
  return true;
}

inline bool cross_poly(Poly &a, Poly &b){
  int n1 = a.size(), n2 = b.size();
  rep(i,n2)if(inter_pos(a,b[i]))return true;
  rep(i,n1)if(inter_pos(b,a[i]))return true;
  rep(i,n1)rep(j,n2)
    if(is_cp(L(a[i],a[(i+1)%n1]),L(b[j],b[(j+1)%n2])))return true;
  return false;
}

void fdfs(int v){
  use[v] = true;
  for(int i=0;i<g[v].size();i++){
    if(!use[g[v][i]])fdfs(g[v][i]);
  }
  vs.pb(v);
}

void rdfs(int v,int k){
  use[v] = true;
  ord[v] = k;
  for(int i=0;i<rg[v].size();i++){
    if(!use[rg[v][i]])rdfs(rg[v][i],k);
  }
}

inline int scc(){
  memset(use,0,sizeof(use));
  vs.clear();
  for(int i=0;i<n;i++){
    if(!use[i])fdfs(i);
  }

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

int main(){
  while(scanf("%d%d",&n,&d), n+d){
    rep(i,n){
      tri[i].resize(3);
      scanf("%lf%lf",&tri[i][0].real(),&tri[i][0].imag());
      scanf("%lf%lf",&tri[i][1].real(),&tri[i][1].imag());
      scanf("%lf%lf",&tri[i][2].real(),&tri[i][2].imag());
      tri[i] = convex_hull(tri[i]);

      rect[i].clear();
      rep(j,3){
	int n1 = (j+1)%3, n2 = (j+2)%3;
	if(EQ(abs(tri[i][n1]-tri[i][j]),abs(tri[i][n2]-tri[i][j]))){
	  rect[i].pb(tri[i][n1]); rect[i].pb(tri[i][n2]); break;
	}
      }

      P ver = (D)d*unit((rect[i][0]-rect[i][1])*P(0,-1));
      rect[i].pb(ver+rect[i][1]); rect[i].pb(ver+rect[i][0]);
      rect[i] = convex_hull(rect[i]);
    }

    rep(i,n){g[i].clear(); rg[i].clear();}
    rep(i,n){
      rep(j,n){
	if(i==j)continue;
	if(cross_poly(rect[i],tri[j])){g[i].pb(j); rg[j].pb(i);}
      }
    }


    int cmp = scc();

    int in[110] = {0};
    rep(i,n){
      rep(j,g[i].size())if(ord[g[i][j]] != ord[i])in[ord[g[i][j]]]++;
    }
  
    int res = 0;
    rep(i,cmp)if(!in[i])res++;
    printf("%d\n",res);
      
  }
}
accuracy: 1
time_ms: 10
memory_kb: 1148
final_rank: 5

code_snippet: #include<cstdio>
#include<vector>
#include<complex>
#include<cstring>
#include<algorithm>

#define rep(i,a) for(int i=0;i<a;i++)
#define EQ(a,b) (abs((a)-(b))<EPS)
#define pb push_back
#define fs first
#define sc second
using namespace std;

typedef double D;
typedef complex<D> P;
typedef pair<P,P> L;
typedef vector<P> Poly;

const D EPS = 1e-8;

namespace std{
  bool operator<(const P &a,const P &b){
    return EQ(real(a),real(b))?imag(a)<imag(b):real(a)<real(b);
  }
}

vector<int> g[110];
vector<int> rg[110];
vector<int> vs;
bool use[110];
int ord[110];
int n,d;
Poly tri[110];
Poly rect[110];

P unit(P p){return p/abs(p);}
D dot(P x,P y){return real(conj(x)*y);}
D cross(P x,P y){return imag(conj(x)*y);}

vector<P> convex_hull(vector<P> v){
  int n = v.size(), k = 0;
  sort(v.begin(),v.end());
  vector<P> r(2*n);
  for(int i=0;i<n;i++){
    while(k>1 && cross(r[k-1]-r[k-2],v[i]-r[k-1]) <= EPS)k--;
    r[k++] = v[i];
  }
  for(int i=n-2,t=k;i>=0;i--){
    while(k>t && cross(r[k-1]-r[k-2],v[i]-r[k-1]) <= EPS)k--;
    r[k++] = v[i];
  }
  r.resize(k-1);
  return r;
}

int ccw(P a,P b,P c){
  b -= a; c -= a;
  if(cross(b,c)>EPS)return 1;
  if(cross(b,c)<-EPS)return -1;
  if(dot(b,c)<-EPS)return 2;
  if(abs(b)<abs(c))return -2;
  return 0;
}

bool is_cp(L a,L b){
  if(ccw(a.fs,a.sc,b.fs)*ccw(a.fs,a.sc,b.sc)<=0)
    if(ccw(b.fs,b.sc,a.fs)*ccw(b.fs,b.sc,a.sc)<=0)return true;
  return false;
}

bool inter_pos(Poly &p,P &x){
  int s = p.size();
  if(!s)return false;
  rep(i,s)if(ccw(p[i],p[(i+1)%s],x)==-1)return false;
  return true;
}

bool cross_poly(Poly &a, Poly &b){
  int n1 = a.size(), n2 = b.size();
  rep(i,n2)if(inter_pos(a,b[i]))return true;
  rep(i,n1)if(inter_pos(b,a[i]))return true;
  rep(i,n1)rep(j,n2)
    if(is_cp(L(a[i],a[(i+1)%n1]),L(b[j],b[(j+1)%n2])))return true;
  return false;
}

void fdfs(int v){
  use[v] = true;
  for(int i=0;i<g[v].size();i++){
    if(!use[g[v][i]])fdfs(g[v][i]);
  }
  vs.pb(v);
}

void rdfs(int v,int k){
  use[v] = true;
  ord[v] = k;
  for(int i=0;i<rg[v].size();i++){
    if(!use[rg[v][i]])rdfs(rg[v][i],k);
  }
}

int scc(){
  memset(use,0,sizeof(use));
  vs.clear();
  for(int i=0;i<n;i++){
    if(!use[i])fdfs(i);
  }

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

int main(){
  while(scanf("%d%d",&n,&d), n+d){
    rep(i,n){
      tri[i].resize(3);
      scanf("%lf%lf",&tri[i][0].real(),&tri[i][0].imag());
      scanf("%lf%lf",&tri[i][1].real(),&tri[i][1].imag());
      scanf("%lf%lf",&tri[i][2].real(),&tri[i][2].imag());
      tri[i] = convex_hull(tri[i]);

      rect[i].clear();
      rep(j,3){
	int n1 = (j+1)%3, n2 = (j+2)%3;
	if(EQ(abs(tri[i][n1]-tri[i][j]),abs(tri[i][n2]-tri[i][j]))){
	  rect[i].pb(tri[i][n1]); rect[i].pb(tri[i][n2]); break;
	}
      }

      P ver = (D)d*unit((rect[i][0]-rect[i][1])*P(0,-1));
      rect[i].pb(ver+rect[i][1]); rect[i].pb(ver+rect[i][0]);
      rect[i] = convex_hull(rect[i]);
    }

    rep(i,n){g[i].clear(); rg[i].clear();}
    rep(i,n){
      rep(j,n){
	if(i==j)continue;
	if(cross_poly(rect[i],tri[j])){g[i].pb(j); rg[j].pb(i);}
      }
    }


    int cmp = scc();

    int in[110] = {0};
    rep(i,n){
      rep(j,g[i].size())if(ord[g[i][j]] != ord[i])in[ord[g[i][j]]]++;
    }
  
    int res = 0;
    rep(i,cmp)if(!in[i])res++;
    printf("%d\n",res);
      
  }
}
accuracy: 1
time_ms: 10
memory_kb: 1148
final_rank: 5

code_snippet: #include<iostream>
#include<vector>
#include<complex>
#include<cstring>
#include<algorithm>

#define rep(i,a) for(int i=0;i<a;i++)
#define EQ(a,b) (abs((a)-(b))<EPS)
#define pb push_back
#define fs first
#define sc second
using namespace std;

typedef double D;
typedef complex<D> P;
typedef pair<P,P> L;
typedef vector<P> Poly;

const D EPS = 1e-8;

namespace std{
  bool operator<(const P &a,const P &b){
    return EQ(real(a),real(b))?imag(a)<imag(b):real(a)<real(b);
  }
}

vector<int> g[110];
vector<int> rg[110];
vector<int> vs;
bool use[110];
int ord[110];
int n,d;
Poly tri[110];
Poly rect[110];

P unit(P p){return p/abs(p);}
pair<P,P> norm(P p){return make_pair(p*P(0,1),p*P(0,-1));}

D dot(P x,P y){return real(conj(x)*y);}
D cross(P x,P y){return imag(conj(x)*y);}

vector<P> convex_hull(vector<P> v){
  int n = v.size(), k = 0;
  sort(v.begin(),v.end());
  vector<P> r(2*n);
  for(int i=0;i<n;i++){
    while(k>1 && cross(r[k-1]-r[k-2],v[i]-r[k-1]) <= EPS)k--;
    r[k++] = v[i];
  }
  for(int i=n-2,t=k;i>=0;i--){
    while(k>t && cross(r[k-1]-r[k-2],v[i]-r[k-1]) <= EPS)k--;
    r[k++] = v[i];
  }
  r.resize(k-1);
  return r;
}

int ccw(P a,P b,P c){
  b -= a; c -= a;
  if(cross(b,c)>EPS)return 1;
  if(cross(b,c)<-EPS)return -1;
  if(dot(b,c)<-EPS)return 2;
  if(abs(b)<abs(c))return -2;
  return 0;
}

bool is_cp(L a,L b){
  if(ccw(a.fs,a.sc,b.fs)*ccw(a.fs,a.sc,b.sc)<=0)
    if(ccw(b.fs,b.sc,a.fs)*ccw(b.fs,b.sc,a.sc)<=0)return true;
  return false;
}

bool inter_pos(Poly p,P x){
  int s = p.size();
  if(!s)return false;
  rep(i,s)if(ccw(p[i],p[(i+1)%s],x)==-1)return false;
  return true;
}

bool cross_poly(Poly a, Poly b){
  int n1 = a.size(), n2 = b.size();
  rep(i,n2)if(inter_pos(a,b[i]))return true;
  rep(i,n1)if(inter_pos(b,a[i]))return true;
  rep(i,n1)rep(j,n2)
    if(is_cp(L(a[i],a[(i+1)%n1]),L(b[j],b[(j+1)%n2])))return true;
  return false;
}

void fdfs(int v){
  use[v] = true;
  for(int i=0;i<g[v].size();i++){
    if(!use[g[v][i]])fdfs(g[v][i]);
  }
  vs.pb(v);
}

void rdfs(int v,int k){
  use[v] = true;
  ord[v] = k;
  for(int i=0;i<rg[v].size();i++){
    if(!use[rg[v][i]])rdfs(rg[v][i],k);
  }
}

int scc(){
  memset(use,0,sizeof(use));
  vs.clear();
  for(int i=0;i<n;i++){
    if(!use[i])fdfs(i);
  }

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

int main(){
  while(cin >> n >> d, n+d){
    rep(i,n){
      tri[i].resize(3);
      cin >> tri[i][0].real() >> tri[i][0].imag();
      cin >> tri[i][1].real() >> tri[i][1].imag();
      cin >> tri[i][2].real() >> tri[i][2].imag();
      tri[i] = convex_hull(tri[i]);

      rect[i].clear();
      rep(j,3){
	int n1 = (j+1)%3, n2 = (j+2)%3;
	if(EQ(abs(tri[i][n1]-tri[i][j]),abs(tri[i][n2]-tri[i][j]))){
	  rect[i].pb(tri[i][n1]); rect[i].pb(tri[i][n2]); break;
	}
      }

      P ver = (D)d*unit(norm(rect[i][0]-rect[i][1]).sc);
      rect[i].pb(ver+rect[i][1]); rect[i].pb(ver+rect[i][0]);
      rect[i] = convex_hull(rect[i]);
    }

    rep(i,n){g[i].clear(); rg[i].clear();}
    rep(i,n){
      rep(j,n){
	if(i==j)continue;
	if(cross_poly(rect[i],tri[j])){g[i].pb(j); rg[j].pb(i);}
      }
    }


    int cmp = scc();

    int in[110] = {0};
    rep(i,n){
      rep(j,g[i].size())if(ord[g[i][j]] != ord[i])in[ord[g[i][j]]]++;
    }
  
    int res = 0;
    rep(i,cmp)if(!in[i])res++;
    cout << res << endl;
      
  }
}
accuracy: 1
time_ms: 10
memory_kb: 1316
final_rank: 9

code_snippet: #include<iostream>
#include<vector>
#include<cfloat>
#include<cassert>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
#define rep(i, n) for ( int i = 0; i < (int)n; i++)
#define EPS (1e-8)
#define equals(a, b) (fabs((a) - (b)) < EPS )
#define dle(a, b) (equals(a, b) || a < b )
#define MAX 100
class Point{
public:
double x, y;
  Point ( double x = 0, double y = 0):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 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;
  }
};

typedef Point Vector;
typedef vector<Point> Polygon;

double norm( Vector a ){ return a.x*a.x + a.y*a.y; }
double dot( Vector a, Vector b ){ return a.x*b.x + a.y*b.y; }
double cross( Vector a, Vector b ){ return a.x*b.y - a.y*b.x; }
static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw( Point p0, Point p1, 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;
}

bool isIntersect(Point p1, Point p2, Point p3, Point p4){
  return ( ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
	   ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0 );
}

bool isInside(Polygon gon, Point p ){
  for ( int i = 0; i < gon.size(); i++ ){
    if ( ccw(gon[i], gon[(i+1)%gon.size()], p) == CLOCKWISE ) return false;
  }
  return true;
}

class Triangle{
public:
  vector<Point> P;
  Triangle(){ P.resize(3);}
  void normalize(){
    vector<Point> tmp(3);
    if ( norm(P[0]-P[1]) == norm(P[0]-P[2]) ){
      tmp[0] = P[1]; tmp[1] = P[2]; tmp[2] = P[0];
    } else if ( norm(P[1]-P[0]) == norm(P[1]-P[2]) ){
      tmp[0] = P[0]; tmp[1] = P[2]; tmp[2] = P[1];
    } else if ( norm(P[2]-P[0]) == norm(P[2]-P[1]) ){
      tmp[0] = P[0]; tmp[1] = P[1]; tmp[2] = P[2];
    }
    P = tmp;
    if ( ccw(P[0], P[1], P[2]) != COUNTER_CLOCKWISE ) {
      swap(P[0], P[1]);
    }
  }
};

class Graph{
public:
  int n;
  vector<vector<int> > adj;
  Graph(int n = 0):n(n){
    adj.resize(n);
    rep(i, n) adj[i].clear();
  }
  void connect(int i, int j){ adj[i].push_back(j); }
  void transpose(){
    vector<vector<int> > nadj;
    nadj.resize(n);
    rep(i, n) nadj[i].clear();
    rep(i, n) rep(j, adj[i].size()) nadj[adj[i][j]].push_back(i);
    rep(i, n) adj[i] = nadj[i];
  }
};

int n;
double d;
Triangle T[MAX];

Graph g;
int visited[MAX], finish[MAX], t;
vector<int> com;

bool overlapPolygon(Polygon p1, Polygon p2){
  rep(i, p1.size()) if ( isInside(p2, p1[i]) ) return true;
  rep(i, p2.size()) if ( isInside(p1, p2[i]) ) return true;
  rep(i, p1.size()) rep(j, p2.size()){
    if ( isIntersect(p1[i], p1[(i+1)%p1.size()], p2[j], p2[(j+1)%p2.size()]))
      return true;
  }
  return false;
}

bool overlap( int t1, int t2){
  Triangle s = T[t1];
  vector<Point> rect, tri;
  Point c = Point((s.P[0].x+s.P[1].x)/2, (s.P[0].y+s.P[1].y)/2);
  Vector v = s.P[2] - c;
  double a = v.abs();
  v.x = d*v.x/a;
  v.y = d*v.y/a;
  Point l = s.P[0] + v;
  Point r = s.P[1] + v;
  rect.push_back(s.P[1]);
  rect.push_back(r);
  rect.push_back(l);
  rect.push_back(s.P[0]);
  tri = T[t2].P;
  return overlapPolygon(rect, tri);
}

void dfs(int &u){
  visited[u] = t++;
  rep(i, g.adj[u].size()){
    int v = g.adj[u][i];
    if ( visited[v] == -1 ) dfs(v);
  }
  finish[u] = t++;
}

void dfsT(int &u){
  com.push_back(u);
  visited[u] = 1;
  rep(i, g.adj[u].size()){
    int v = g.adj[u][i];
    if ( visited[v] == 0 ) dfsT(v);
  }
}

void makeGraph(){
  g = Graph(n);
  rep(i, n) rep(j, n){
    if ( i != j && overlap(i, j) ) {
      g.connect(i, j);
    }
  }
}

int scc(){
  int id[MAX];
  bool indeg[MAX];
  rep(i, n) visited[i] = finish[i] = -1;
  t = 0;
  rep(i, n) if ( visited[i] == -1 ) dfs(i);
  g.transpose();
  vector<pair<int, int> > order;
  rep(i, n) order.push_back(make_pair(finish[i], i));
  sort(order.begin(), order.end());
  rep(i, n) visited[i] = 0;
  int ncom = 0;
  for ( int i = n-1; i >= 0; i-- ){
    int u = order[i].second;
    com.clear();
    if ( visited[u] == 0 ) {
      dfsT(u);
      rep(c, com.size()) id[com[c]] = ncom;
      ncom++;
    }
  }
  int cnt = 0;
  g.transpose();
  rep(i, ncom) indeg[i] = false;
  rep(u, n) rep(i, g.adj[u].size()){
    int v = g.adj[u][i];
    if ( id[v] != id[u] ) indeg[id[v]] = true;
  }
  rep(i, ncom) if (!indeg[i]) cnt++;
  return cnt;
}

main(){
  while( cin >> n >> d && n ){
    rep(i, n){
      Triangle t;
      rep(j, 3) cin >> t.P[j].x >> t.P[j].y;
      t.normalize();
      T[i] = t;
    }
    makeGraph();
    cout << scc() << endl;
  }
}
accuracy: 1
time_ms: 20
memory_kb: 1284
final_rank: 10

code_snippet: #include<iostream>
#include<sstream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
using namespace std;

#define rep(i,n) for(int i=0;i<(int)n;i++)
#define each(i,c) for(__typeof(c.begin()) i=c.begin();i!=c.end();i++)
#define pb push_back
#define mp make_pair
#define all(c) c.begin(),c.end()
#define dbg(x) cerr<<__LINE__<<": "<<#x<<" = "<<(x)<<endl

typedef vector<int> vi;
typedef pair<int,int> pi;
typedef long long ll;
const int inf=(int)1e9;
const double EPS = 1e-9, 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) > 0)   return +1;		// counter clockwise
	if(cross(b, c) < 0)   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;
}
G convex_hull(G ps) {
  int n = ps.size(), k = 0;
  sort(ps.begin(), ps.end());
  G ch(2*n);
  for (int i = 0; i < n; ch[k++] = ps[i++]) // lower-hull
    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--]) // upper-hull
    while (k >= t && ccw(ch[k-2], ch[k-1], ps[i]) <= 0) --k;
  ch.resize(k-1);
  return ch;
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
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]);
}
double distanceSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
enum { OUT, ON, IN };
int contains(const G& g, const P& p) {
  bool in = false;
  for (int i = 0; i < g.size(); ++i) {
    P a = curr(g,i) - p, b = next(g,i) - p;
    if (imag(a) > imag(b)) swap(a, b);
    if (imag(a) <= 0 && 0 < imag(b))
      if (cross(a, b) < 0) in = !in;
    if (cross(a, b) == 0 && dot(a, b) <= 0) return ON;
  }
  return in ? IN : OUT;
}
#include<stack>
void visit(const vector<vi> &g, int v, vector<vi>& scc,
    stack<int> &S, vector<bool> &inS,
    vector<int> &low, vector<int> &num, int& time) {
  low[v] = num[v] = ++time;
  S.push(v); inS[v] = true;
  each(e, g[v]) {
    int w = *e;
    if (num[w] == 0) {
      visit(g, w, scc, S, inS, low, num, time);
      low[v] = min(low[v], low[w]);
    } else if (inS[w])
      low[v] = min(low[v], num[w]);
  }
  if (low[v] == num[v]) {
    scc.push_back(vector<int>());
    while (1) {
      int w = S.top(); S.pop(); inS[w] = false;
      scc.back().push_back(w);
      if (v == w) break;
    }
  }
}
void stronglyConnectedComponents(const vector<vi>& g,
    vector<vi>& scc) {
  const int n = g.size();
  vector<int> num(n), low(n);
  stack<int> S;
  vector<bool> inS(n);
  int time = 0;
  rep(u, n) if (num[u] == 0)
    visit(g, u, scc, S, inS, low, num, time);
}

int n, d;
vector<vi> g;

int main(){
	while(cin >> n >> d, n || d){
		g.clear(); g.resize(n);
		vector<G> tri;
		rep(i, n){
			int t = -1;
			G p(3);
			double l[3];
			rep(j, 3) cin >> p[j].real() >> p[j].imag();
			rep(j, 3) l[j] = abs(p[j] - p[(j + 1) % 3]);
			rep(j, 3) if(abs(l[j] - l[(j + 1) % 3]) < EPS){
				t = (j + 1) % 3;
				break;
			}
			assert(t >= 0);
			if(t) swap(p[t], p[0]);
			tri.pb(p);
		}
		
		rep(i, n){
			G &p = tri[i];
			P dir = p[0] - (p[1] + p[2]) * 0.5;
			dir *= d / abs(dir);
			
			G ps;
			ps.pb(p[1]); ps.pb(p[2]);
			ps.pb(p[1] + dir); ps.pb(p[2] + dir);
			ps = convex_hull(ps);
			
			rep(j, n){
				bool ok = 0;
				rep(k, 3){
					rep(l, 4) if(distanceSP(L(ps[l], ps[(l + 1) % 4]), tri[j][k])
						< 0.01) ok = 1;
					if(contains(ps, tri[j][k]) != OUT) ok = 1;
				}
				if(ok) g[i].pb(j);
			}
		}
		
		int ans = 0;
		map<int, int> to;
		vector<vi> scc;
		stronglyConnectedComponents(g, scc);
		int m = scc.size();
		vi in(m);
		
		rep(i, m) rep(j, scc[i].size()){
			to[scc[i][j]] = i;
		}
		rep(i, n) rep(j, g[i].size()){
			int a = to[i], b = to[g[i][j]];
			if(a != b) in[b]++;
		}
		rep(i, m) if(in[i] == 0) ans++;
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 1316
final_rank: 14

code_snippet: #include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
const double PI = acos(-1);
const double EPS = 1e-8;

typedef complex<double> P;
namespace std {
  bool operator < (const P& a, const P& b) {
    // if (abs(a-b)<EPS) return 0;
    return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
  }
}
double cross(const P& a, const P& b) {
  return imag(conj(a)*b);
}
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);
  }
  L() {}
};
typedef vector<P> G;
#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]
struct C {
  P p; double r;
  C(const P &p, double r) : p(p), r(r) { }
};

int ccw(P a, P b, P c) {
  b -= a; c -= a;
  if (cross(b, c) > 0)   return +1;       // counter clockwise
  if (cross(b, c) < 0)   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;
}

bool intersectLL(const L &l, const L &m) {
  return abs(cross(l[1]-l[0], m[1]-m[0])) > EPS || // non-parallel
         abs(cross(l[1]-l[0], m[0]-l[0])) < EPS;   // same line
}
bool intersectLS(const L &l, const L &s) {
  return cross(l[1]-l[0], s[0]-l[0])*       // s[0] is left of l
         cross(l[1]-l[0], s[1]-l[0]) < EPS; // s[1] is right of l
}
bool intersectLP(const L &l, const P &p) {
  return abs(cross(l[1]-p, l[0]-p)) < EPS;
}
bool intersectSS(const L &s, const L &t) {
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSS2(const L &s, const L &t) { // 接しているやつは交差と考えない
  REP(i, 2) {
    if (ccw(s[0], s[1], t[i]) == 0) {
      int c = ccw(s[0],s[1],t[!i]);
      if (s[0] == t[i]) {
        if (c!=-2&&c) return 0;
      } else if (s[1] == t[i]) {
        if (c!=2&&c) return 0;
      } else if (abs(c)==1) return 0;
    }
  }
  return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 &&
         ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;
}
bool intersectSP(const L &s, const P &p) {
  return abs(s[0]-p)+abs(s[1]-p)-abs(s[1]-s[0]) < EPS; // triangle inequality
}
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 reflection(const L &l, const P &p) {
  return p + P(2,0) * (projection(l, p) - p);
}
double distanceLP(const L &l, const P &p) {
  return abs(p - projection(l, p));
}
double distanceLL(const L &l, const L &m) {
  return intersectLL(l, m) ? 0 : distanceLP(l, m[0]);
}
double distanceLS(const L &l, const L &s) {
  if (intersectLS(l, s)) return 0;
  return min(distanceLP(l, s[0]), distanceLP(l, s[1]));
}
double distanceSP(const L &s, const P &p) {
  const P r = projection(s, p);
  if (intersectSP(s, r)) return abs(r - p);
  return min(abs(s[0] - p), abs(s[1] - p));
}
bool convex_contain(const G &g, const P &p) { // 半時計回りを仮定
  REP(i,g.size())
    if (ccw(g[i], next(g, i), p) == -1 && distanceSP(L(g[i],next(g,i)), p) > 0.01) return 0;
  return 1;
}

double distanceSS(const L &s, const L &t) {
  if (intersectSS(s, t)) return 0;
  return min(min(distanceSP(s, t[0]), distanceSP(s, t[1])),
             min(distanceSP(t, s[0]), distanceSP(t, s[1])));
}

bool intersectGG(const G &g1, const G &g2) {
  if (convex_contain(g1, g2[0])) return 1;
  if (convex_contain(g2, g1[0])) return 1;
  REP(i,g1.size()) REP(j,g2.size()) {
    if (distanceSS(L(g1[i], next(g1, i)), L(g2[j], next(g2, j))) <= 0.01) return 1;
  }
  return 0;
}

typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void visit(const Graph &g, int v, vector< vector<int> >& scc,
    stack<int> &S, vector<bool> &inS,
    vector<int> &low, vector<int> &num, int& time) {
  low[v] = num[v] = ++time;
  S.push(v); inS[v] = true;
  FOR(e, g[v]) {
    int w = e->dst;
    if (num[w] == 0) {
      visit(g, w, scc, S, inS, low, num, time);
      low[v] = min(low[v], low[w]);
    } else if (inS[w])
      low[v] = min(low[v], num[w]);
  }
  if (low[v] == num[v]) {
    scc.push_back(vector<int>());
    while (1) {
      int w = S.top(); S.pop(); inS[w] = false;
      scc.back().push_back(w);
      if (v == w) break;
    }
  }
}
void stronglyConnectedComponents(const Graph& g,
    vector< vector<int> >& scc) {
  const int n = g.size();
  vector<int> num(n), low(n);
  stack<int> S;
  vector<bool> inS(n);
  int time = 0;
  REP(u, n) if (num[u] == 0)
    visit(g, u, scc, S, inS, low, num, time);
}

// 強連結成分を縮約する
Graph edgeContractionAndSort(const Graph &g) {
  int n = g.size();
  vector<vector<int> > scc;
  stronglyConnectedComponents(g, scc);
  int m = scc.size();
  vector<int> cmp(n);
  REP(i,m) FOR(jt, scc[i])
    cmp[*jt] = i;
  map<pii, bool> mp;
  Graph res(m);
  REP(i,n) {
    int a = cmp[i];
    FOR(it,g[i]) {
      int b = cmp[it->dst];
      if (a != b) {
        if (mp.count(pii(a,b)) == 0) {
          mp[pii(a,b)] = 1;
          res[a].push_back(Edge(a,b,1));
        }
      }
    }
  }
  return res;
}


G triangle[100];
int deg[100];

int main() {
  int n, d;
  while(cin>>n>>d,n||d) {
    REP(i,n) {
      triangle[i].clear();
      REP(j,3) {
        P p; cin >> p.real() >> p.imag();
        triangle[i].push_back(p);
      }
      if (abs(abs(triangle[i][0]-triangle[i][1]) - abs(triangle[i][0]-triangle[i][2])) < EPS) {
        swap(triangle[i][0], triangle[i][2]);
      }
      if (abs(abs(triangle[i][1]-triangle[i][0]) - abs(triangle[i][1]-triangle[i][2])) < EPS) {
        swap(triangle[i][1], triangle[i][2]);
      }
      if (cross(triangle[i][1]-triangle[i][0], triangle[i][2]-triangle[i][0]) < 0) {
        swap(triangle[i][0], triangle[i][1]);
      }
      // REP(j,3) cout << triangle[i][j] << " ";
      // cout << endl;
    }
    Graph g(n);
    REP(i,n) {
      G rect;
      P p = triangle[i][1] - triangle[i][0];
      p /= abs(p);
      p *= P(0,1);
      p *= d;
      rect.push_back(triangle[i][0]);
      rect.push_back(triangle[i][1]);
      rect.push_back(triangle[i][1] + p);
      rect.push_back(triangle[i][0] + p);
      REP(j,n) {
        if (i == j) continue;
        if (intersectGG(rect, triangle[j])) {
          //cout << i << " " << j << endl;
          g[i].push_back(Edge(i,j,0));
        }
      }
    }
    Graph g2 = edgeContractionAndSort(g);
    memset(deg,0,sizeof(deg));
    FOR(it, g2) {
      FOR(e, *it) {
        deg[e->dst]++;
      }
    }
    int ans = 0;
    REP(i,g2.size()) {
      if (deg[i] == 0) ans++;
    }
    cout << ans << endl;
  }
}
accuracy: 1
time_ms: 70
memory_kb: 1304
final_rank: 17

code_snippet: #include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cfloat>
#include <map>
#include <utility>
#include <set>
#include <iostream>
#include <cassert>
#include <memory>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <functional>
#include <sstream>
#include <complex>
#include <stack>
#include <queue>
using namespace std;

const double EPS = 0.01;

typedef complex<double> P,point;
typedef vector<P> G,polygon;
namespace std {bool operator < (const P& a, const P& b) {return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);} }
double cross(const P& a, const P& b) {return imag(conj(a)*b);}
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);} };
int ccw(P a, P b, P c) {
	b -= a; c -= a;
	if (cross(b, c) > 0)   return +1;
	if (cross(b, c) < 0)   return -1;
	if (dot(b, c) < 0) return +2;
	if (norm(b) < norm(c)) return -2;
	return 0;
}

bool intersectSS(const L &s, const L &t) {return ccw(s[0],s[1],t[0])*ccw(s[0],s[1],t[1]) <= 0 && ccw(t[0],t[1],s[0])*ccw(t[0],t[1],s[1]) <= 0;}

#define curr(P, i) P[i]
#define next(P, i) P[(i+1)%P.size()]

 
double area(vector<P> p){
	double S = 0 ; 
	p.push_back(p[0]);
	/*　多角形の面積公式 (反時計回りの場合) */
	for(int i = 0 ; i < p.size()-1 ; i++){
		S += (p[i].real() - p[i+1].real()) * (p[i].imag()+p[i+1].imag());
	}
	S /= 2.0;
	return S;
}
bool contains(vector<P> &a,P b){
	//b = (-10000,-10000);
	double ans = 0;
	for(int i = 0 ; i < a.size() ; i++){
		vector<P> w;
		w.push_back(a[i]);
		w.push_back(a[(i+1)%a.size()]);
		w.push_back(b);
		ans += abs(area(w));
	}
	ans = abs(ans);
	//cout << a[0] << " " << a[1] << " " << a[2] << " " << a[3] << " " << b << " " << (fabs(abs(area(a)) - ans ) < EPS) << endl;
	//cout << ans << " " << abs(area(a)) << " " << a.size() << endl;
	return fabs(abs(area(a)) - ans ) < EPS;
}

/*
	幾何: 
		・凸多角形の点包含判定
		・凸多角形同士の線分交差判定
	グラフ:
		・強連結成分分解
		・入次数数える
*/

int n;


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

int wf[100][100]={};

int main(){
	double d;
	while(cin >> n >> d && n ){
		memset(wf,0,sizeof(wf));
		for(int i = 0 ; i < n ; i++) 
			wf[i][i] = 1;
		vector<G> g(n);
		vector<G> g2(n);
		for(int i = 0 ; i < n ; i++){
			double x1,x2,x3,y1,y2,y3;
			cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
			g[i].push_back(P(x1,y1));
			g[i].push_back(P(x2,y2));
			g[i].push_back(P(x3,y3));
			double A = abs( P(x2,y2) - P(x1,y1) );
			double B = abs( P(x2,y2) - P(x3,y3) );
			double C = abs( P(x3,y3) - P(x1,y1) );
			L l(P(-1,-1),P(-1,-1));
			if( eq(A,B) ) l = L( P(x3,y3) , P(x1,y1) );
			else if( eq(A,C) ) l = L( P(x2,y2) , P(x3,y3) );
			else if( eq(B,C) ) l = L( P(x2,y2) , P(x1,y1) );
			else while(1){}
			
			assert( !( eq(A,B) && eq(B,C) ) );
			P r = l[1] - l[0];
			r = P(-r.imag(),r.real());
			r /= abs(r);
			
			//cout << A << " " << B << " " << C << " " << l[0] << "-" << l[1] << " " << r << endl;
			for(int coef = -1 ; coef <= 1 ; coef += 2 ){
				vector<P> XX;
				XX.push_back(l[0]);
				XX.push_back(l[0] + coef * d * r );
				XX.push_back(l[1] + coef * d * r );			
				XX.push_back(l[1]);
				int ok = 1;
				
				for(int j = 0 ; j < 3 ; j++){
					if( !contains(XX,g[i][j]) ){
						ok = 0;
					}
				}
				if( ok ) {
					if( g2[i].size() ) assert(0);
					g2[i] = XX;
				}
			}
		}
		for(int i = 0 ; i < n ; i++){
			for(int j = 0 ; j < n ; j++){
				if( i != j ) {
					int ok = 0;
					for(int l = 0 ; l < 3 ; l++){
						if( contains(g2[i],g[j][l]) ){
							ok = 1;
						}
					}
					for(int k = 0 ; k < 4 ; k++){
						for(int l = k+1 ; l < 4 ; l++){
							for(int m = 0 ; m < 3 ; m++){
								for(int o = m+1 ; o < 3 ; o++){
									if( intersectSS(L(g2[i][k],g2[i][l]),L(g[j][m],g[j][o])) ){
										ok = 1;
										
									}
								}
							}
						}
					}
					if( ok ) {
						wf[i][j] = 1;
					}
				}
			}
		}
		for(int i = 0 ; i < n ; i++)
			for(int j = 0 ; j < n ; j++)
				for(int k = 0 ; k < n ; k++)
					wf[j][k] |= wf[j][i] & wf[i][k];
	
		
		int in[100] = {} , id[100] = {} , cur = 0;
		for(int i = 0 ; i < n ; i++)
			id[i] = -1;
		
		for(int i = 0 ; i < n ; i++){
			if( id[i] == -1 ){
				for(int j = 0 ; j < n ; j++){
					if( wf[i][j] & wf[j][i] ){
						id[j] = cur;
					}
				}
				cur++;
			}
		}
		for(int i = 0 ; i < n ; i++){
			for(int j = 0 ; j < n ; j++){
				if(wf[i][j] && id[i] != id[j]) in[id[j]]++;
			}
		}
		int ans = 0;
		for(int i = 0 ; i < cur ; i++){
			if( !in[i] ){
				ans++;
			}
		}
		cout << ans << endl;
	}
}
accuracy: 1
time_ms: 140
memory_kb: 1044
final_rank: 19

code_snippet: #include<iostream>
#include<vector>
#include<cfloat>
#include<cassert>
#include<cmath>
#include<vector>
#include<algorithm>

using namespace std;
#define rep(i, n) for ( int i = 0; i < (int)n; i++)
//#define EPS (1e-8)
#define EPS 0.01
#define equals(a, b) (fabs((a) - (b)) <= EPS )
#define dle(a, b) (equals(a, b) || a < b )

#define MAX 100

class Point{
    public:
    double x, y;
    
    Point ( double x = 0, double y = 0): 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 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;
    }
};
typedef Point Vector;
typedef vector<Point> Polygon;

double norm( Vector a ){ return a.x*a.x + a.y*a.y; }
double abs( Vector a ) { return sqrt(norm(a)); }
double dot( Vector a, Vector b ){ return a.x*b.x + a.y*b.y; }
double cross( Vector a, Vector b ){ return a.x*b.y - a.y*b.x; }
static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw( Point p0, Point p1, 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;
}
bool isIntersect(Point p1, Point p2, Point p3, Point p4){
    return ( ccw(p1, p2, p3) * ccw(p1, p2, p4) <= 0 &&
	     ccw(p3, p4, p1) * ccw(p3, p4, p2) <= 0 );
}

bool isInside(Polygon gon, Point p ){
    for ( int i = 0; i < gon.size(); i++ ){
	if ( ccw(gon[i], gon[(i+1)%gon.size()], p) == CLOCKWISE ) return false;
    }
    return true;
}

class Triangle{
    public:
    vector<Point> P;
    Triangle(){ P.resize(3);}

    void normalize(){
	vector<Point> tmp(3);
	if ( norm(P[0]-P[1]) == norm(P[0]-P[2]) ){
	    tmp[0] = P[1]; tmp[1] = P[2]; tmp[2] = P[0];
	} else if ( norm(P[1]-P[0]) == norm(P[1]-P[2]) ){
	    tmp[0] = P[0]; tmp[1] = P[2]; tmp[2] = P[1];
	} else if ( norm(P[2]-P[0]) == norm(P[2]-P[1]) ){
	    tmp[0] = P[0]; tmp[1] = P[1]; tmp[2] = P[2];
	}
	P = tmp;
	if ( ccw(P[0], P[1], P[2]) != COUNTER_CLOCKWISE ) {
	    swap(P[0], P[1]);
	}
    }

    double getArea(){
	double a = abs(P[0]-P[1]); 
	double b = abs(P[0]-P[2]); 
	double c = abs(P[2]-P[1]); 
	assert(!(a==b && a==c && b==c));
	double s= (a + b + c)/2.0;
	return sqrt(s*(s-a)*(s-b)*(s-c));
    }

};

class Graph{
public:
    int n;
    vector<vector<int> > adj;
    Graph(int n = 0):n(n){
	adj.resize(n);
	rep(i, n) adj[i].clear();
    }
    void connect(int i, int j){ adj[i].push_back(j); }
    void transpose(){
	vector<vector<int> > nadj;
	nadj.resize(n);
	rep(i, n) nadj[i].clear();
	rep(i, n) rep(j, adj[i].size())	nadj[adj[i][j]].push_back(i);
	rep(i, n) adj[i] = nadj[i];
    }
};

int n;
double d;
Triangle T[MAX];

Graph g;
int visited[MAX], finish[MAX], t;
vector<int> com;

bool overlapPolygon(Polygon p1, Polygon p2){
    rep(i, p1.size()) if ( isInside(p2, p1[i]) ) return true;
    rep(i, p2.size()) if ( isInside(p1, p2[i]) ) return true;
    rep(i, p1.size()) rep(j, p2.size()){
      if ( isIntersect(p1[i], p1[(i+1)%p1.size()], p2[j], p2[(j+1)%p2.size()])) return true;
    }
    return false;
}

bool overlap( int t1, int t2){
    Triangle s = T[t1];
    vector<Point> rect, tri;
    Point c = Point((s.P[0].x+s.P[1].x)/2, (s.P[0].y+s.P[1].y)/2);
    Vector v = s.P[2] - c;
    double a = v.abs();
    v.x = d*v.x/a;
    v.y = d*v.y/a;
    Point l = s.P[0] + v;
    Point r = s.P[1] + v;
    rect.push_back(s.P[1]);
    rect.push_back(r);
    rect.push_back(l);
    rect.push_back(s.P[0]);

    assert( isInside(rect, s.P[0]) &&
	    isInside(rect, s.P[1]) &&
	    isInside(rect, s.P[2]));

    tri = T[t2].P;
    return overlapPolygon(rect, tri);
}

void dfs(int &u){
    visited[u] = t++;
    rep(i, g.adj[u].size()){
	int v = g.adj[u][i];
	if ( visited[v] == -1 ) dfs(v);
    }
    finish[u] = t++;
}

void dfsT(int &u){
    com.push_back(u);
    visited[u] = 1;
    rep(i, g.adj[u].size()){
	int v = g.adj[u][i];
	if ( visited[v] == 0 ) dfsT(v);
    }
}

void makeGraph(){
    g = Graph(n);
    rep(i, n) rep(j, n){
	if ( i != j && overlap(i, j) ) {
	    g.connect(i, j);
	}
    }
}

int scc(){
    int id[MAX];
    bool indeg[MAX];

    rep(i, n) visited[i] = finish[i] = -1;
    t = 0;
    rep(i, n) if ( visited[i] == -1 ) dfs(i);

    g.transpose();
    
    vector<pair<int, int> > order;
    rep(i, n) order.push_back(make_pair(finish[i], i));
    sort(order.begin(), order.end());
    
    rep(i, n) visited[i] = 0;
    
    int ncom = 0;
    
    for ( int i = n-1; i >= 0; i-- ){
	int u = order[i].second;
	com.clear();
	if ( visited[u] == 0 ) {
	    dfsT(u);
	    rep(c, com.size()) id[com[c]] = ncom;
	    ncom++;
	}
    }
    
    int cnt = 0;
    g.transpose();

    rep(i, ncom) indeg[i] = false;
    
    rep(u, n) rep(i, g.adj[u].size()){
	int v = g.adj[u][i];
	if ( id[v] != id[u] ) indeg[id[v]] = true;
    }
    rep(i, ncom) if (!indeg[i]) cnt++;
    
    return cnt;
}

main(){
    while( cin >> n >> d && n ){
	rep(i, n){
	    Triangle t;
	    rep(j, 3) cin >> t.P[j].x >> t.P[j].y;
	    t.normalize();
	    T[i] = t;
	}
	double a = T[0].getArea();
	for ( int i = 0; i < n-1; i++ ){
	    for ( int j = i+1; j < n; j++ ){

		Triangle t1 = T[i];
		Triangle t2 = T[j];
		for ( int a= 0; a < 3; a++ ){
		    for ( int b = 0; b < 3; b++ ){
			Point p1 = t1.P[a];
			Point p2 = t1.P[(a+1)%3];
			Point p3 = t2.P[b];
			Point p4 = t2.P[(b+1)%3];
		 
		    }

		}

	    }
	}

	makeGraph();
	cout << scc() << endl;
    }
}
accuracy: 1
time_ms: 20
memory_kb: 984
final_rank: 7

code_snippet: #include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

void stronglyConnectedComponents(const vector<vector<int> >& edges1, vector<vector<int> >& nodes, vector<vector<int> >& edges2)
{
    const int n = edges1.size();

    class Func{
        vector<int> num, low;
        vector<bool> isStk;
        stack<int> stk;
        int time;
    public:
        Func(int n){
            num.assign(n, 0);
            low.assign(n, 0);
            isStk.assign(n, false);
            time = 0;
        }
        void visit(const vector<vector<int> >& edges, int v, vector<vector<int> >& nodes){
            if(num[v] != 0)
                return;
            num[v] = low[v] = ++ time;
            stk.push(v);
            isStk[v] = true;
            for(unsigned i=0; i<edges[v].size(); ++i){
                int w = edges[v][i];
                visit(edges, w, nodes);
                if(isStk[w])
                    low[v] = min(low[v], low[w]);
            }
            if(low[v] == num[v]){
                nodes.push_back(vector<int>());
                for(;;){
                    int w = stk.top();
                    stk.pop();
                    isStk[w] = false;
                    nodes.back().push_back(w);
                    if(v == w)
                        break;
                }
            }
        }
    }func(n);

    for(int i=0; i<n; ++i)
        func.visit(edges1, i, nodes);
    reverse(nodes.begin(), nodes.end()); // DAGÉ·é½ßÉ½]³¹é

    const int m = nodes.size();
    vector<int> index(n); // ³ÌOtÌe¸_ÌDAGÉ¨¯é¸_
    for(int i=0; i<m; ++i){
        for(unsigned j=0; j<nodes[i].size(); ++j)
            index[nodes[i][j]] = i;
    }
    edges2.assign(m, vector<int>());
    vector<vector<bool> > check(m, vector<bool>(m, false));
    for(int i=0; i<n; ++i){
        for(unsigned j=0; j<edges1[i].size(); ++j){
            int v = index[i];
            int w = index[edges1[i][j]];
            if(v != w && !check[v][w]){
                edges2[v].push_back(w);
                check[v][w] = true;
            }
        }
    }
}

const double EPS = 1.0e-10;

class Point
{
public:
    double y, x;
    Point(){
        y = x = 0.0;
    }
    Point(double y0, double x0){
        y = y0;
        x = x0;
    }
    Point operator+(const Point& p) const{
        return Point(y + p.y, x + p.x);
    }
    Point operator-(const Point& p) const{
        return Point(y - p.y, x - p.x);
    }
    Point operator*(double a) const{
        return Point(y * a, x * a);
    }
    Point operator/(double a) const{
        return Point(y / a, x / a);
    }
    double length() const{
        return sqrt(y * y + x * x);
    }
    double dist(const Point& p) const{
        return sqrt(pow(y - p.y, 2) + pow(x - p.x, 2));
    }
    double dot(const Point& p) const{
        return y * p.y + x * p.x; // |a|*|b|*cosÆ
    }
    double cross(const Point& p) const{
        return x * p.y - y * p.x; // |a|*|b|*sinÆ
    }
};

double segmentPointDist(const Point& a1, const Point& a2, const Point& p)
{
    if((a2-a1).dot(p-a1) < 0)
        return a1.dist(p);
    else if((a1-a2).dot(p-a2) < 0)
        return a2.dist(p);
    else
        return abs((a2-a1).cross(p-a1)) / a1.dist(a2);
}

double segmentsDist(const Point& a1, const Point& a2, const Point& b1, const Point& b2)
{
    if(((a2-a1).cross(b1-a1) * (a2-a1).cross(b2-a1) < -EPS) && ((b2-b1).cross(a1-b1) * (b2-b1).cross(a2-b1) < -EPS))
        return 0.0;

    double ret = segmentPointDist(a1, a2, b1);
    ret = min(ret, segmentPointDist(a1, a2, b2));
    ret = min(ret, segmentPointDist(b1, b2, a1));
    ret = min(ret, segmentPointDist(b1, b2, a2));
    return ret;
}

bool convexContain(const vector<Point>& cp, const Point& p)
{
    int n = cp.size();
    bool ret1 = true;
    bool ret2 = true;
    for(int i=0; i<n; ++i){
        double a = (cp[(i+1)%n] - cp[i]).cross(p - cp[i]);
        if(a < -EPS)
            ret1 = false;
        if(a > EPS)
            ret2 = false;
    }
    return ret1 || ret2;
}

bool polygonsCollide(const vector<Point>& cp1, const vector<Point>& cp2)
{
    int n = cp1.size();
    int m = cp2.size();
    for(int i=0; i<n; ++i){
        for(int j=0; j<m; ++j){
            if(segmentsDist(cp1[i], cp1[(i+1)%n], cp2[j], cp2[(j+1)%m]) < 0.01 + EPS)
                return true;
        }
    }

    return convexContain(cp1, cp2[0]) || convexContain(cp2, cp1[0]);
}

int main()
{
    for(;;){
        int n, d;
        cin >> n >> d;
        if(n == 0)
            return 0;

        vector<vector<Point> > p(n, vector<Point>(3));
        for(int i=0; i<n; ++i){
            for(int j=0; j<3; ++j){
                cin >> p[i][j].x >> p[i][j].y;
            }
            if(p[i][0].dist(p[i][2]) > p[i][0].dist(p[i][1]))
                swap(p[i][1], p[i][2]);
            if(p[i][1].dist(p[i][2]) > p[i][0].dist(p[i][1]))
                swap(p[i][0], p[i][2]);
            if((p[i][1] - p[i][0]).cross(p[i][2] - p[i][0]) < 0)
                swap(p[i][0], p[i][1]);
        }

        vector<vector<int> > edges(n);
        for(int i=0; i<n; ++i){
            Point v = p[i][1] - p[i][0];
            v = v / v.length() * d;
            swap(v.y, v.x);
            v.x *= -1;

            vector<Point> p1(4);
            p1[0] = p[i][0];
            p1[1] = p[i][0] + v;
            p1[2] = p[i][1] + v;
            p1[3] = p[i][1];

            for(int j=0; j<n; ++j){
                if(j == i)
                    continue;
                if(polygonsCollide(p1, p[j]))
                    edges[i].push_back(j);
            }
        }

        vector<vector<int> > nodes, edges2;
        stronglyConnectedComponents(edges, nodes, edges2);

        int m = edges2.size();
        vector<bool> check(m, false);
        int ret = m;
        for(int i=0; i<m; ++i){
            for(unsigned j=0; j<edges2[i].size(); ++j){
                if(!check[edges2[i][j]]){
                    check[edges2[i][j]] = true;
                    -- ret;
                }
            }
        }
        cout << ret << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include<cstdio>
#include<cstring>
#include<cmath>
#include<complex>
#include<vector>
#include<algorithm>
#define MAX_N 100
#define M 3
#define L 4
#define EPS (1e-10)
#define MIN (0.01)
using namespace std;
typedef complex<double> P;
typedef vector<int> edges;
typedef vector<edges> graph;
double dot(P a, P b){
	return a.real() * b.real() + a.imag() * b.imag();
}
double cross(P a, P b){
	return a.real() * b.imag() - a.imag() * b.real();
}
double distance_ls_p(P a, P b, P c){
	if(dot(b-a, c-a) < EPS)			return abs(c-a);
	else if(dot(a-b, c-b) < EPS)	return abs(c-b);
	else 							return abs(cross(b-a, c-a)) / abs(b-a);
}
bool is_intersected_ls(P a, P b, P c, P d){
	if(	abs(c-a) < MIN + EPS || abs(d-a) < MIN + EPS ||
		abs(c-b) < MIN + EPS || abs(d-b) < MIN + EPS)
			return true;
	if(distance_ls_p(a, b, c) < MIN + EPS ||
		distance_ls_p(a, b, d) < MIN + EPS ||
		distance_ls_p(c, d, a) < MIN + EPS ||
		distance_ls_p(c, d, b) < MIN + EPS)
			return true;
	return
		(cross(b-a, c-a) * cross(b-a, d-a) < -EPS) &&
		(cross(d-c, a-c) * cross(d-c, b-c) < -EPS);
}
bool contains(P *x, int n, P p){
	double o = cross(p-x[0], x[1]-x[0]);
	for(int i=0;i<n;++i){
		if(distance_ls_p(x[i], x[(i+1)%n], p) < MIN + EPS){
			return true;
		}
	}
	for(int i=0;i<n;++i){
		double d = cross(p-x[i], x[(i+1)%n]-x[i]);
		if(d * o < EPS) return false;
	}
	return true;
}
bool overlap(P *x, int n, P *y, int m){
	for(int j=0;j<m;++j){
		if(contains(x, n, y[j])){
			return true;
		}
	}
	for(int i=0;i<n;++i){
		if(contains(y, m, x[i])){
			return true;
		}
	}
	for(int i=0;i<n;++i){
		int k = (i + 1) % n;
		for(int j=0;j<m;++j){
			int l = (j + 1) % m;
			if(is_intersected_ls(x[i], x[k], y[j], y[l])){
				return true;
			}
		}
	}
	return false;
}
int n, d;
P tr[MAX_N][M];
P sq[MAX_N][L];
graph g, gi, dag;
vector<int> vi;
vector<int> f;
vector<int> c;
void create_squares(){
	for(int i=0;i<n;++i){
		P t = tr[i][1] - tr[i][0];
		P v = P(-t.imag(), t.real());
		if(dot(v, tr[i][2] - tr[i][0]) < -EPS){
			v = -v;
		}
		v = v / abs(v) * double(d);
		sq[i][0] = tr[i][0];		sq[i][1] = tr[i][0] + v;
		sq[i][2] = tr[i][1] + v;	sq[i][3] = tr[i][1];
	}
}
void create_graph(){
	g.clear();
	gi.clear();
	g.resize(n);
	gi.resize(n);
	for(int i=0;i<n;++i){
		for(int j=0;j<n;++j){
			if(overlap(sq[i], L, tr[j], M)){
				g[i].push_back(j);
				gi[j].push_back(i);
			}
		}
	}
}
void dfs(graph &g, int v){
	if(f[v] == 1) return;
	f[v] = 1;
	for(edges::iterator i=g[v].begin(); i!=g[v].end(); ++i){
		dfs(g, *i);
	}
	vi.push_back(v);
}
void dfs_2(graph &g, int v, int label){
	if(f[v] == 1) return;
	f[v] = 1;
	c[v] = label;
	for(edges::iterator i=g[v].begin(); i!=g[v].end(); ++i){
		dfs_2(g, *i, label);
	}
}
void dfs_3(graph &g, int v){
	if(f[v] == 1) return;
	f[v] = 1;
	for(edges::iterator i=g[v].begin(); i!=g[v].end(); ++i){
		dfs_3(g, *i);
	}
	vi.push_back(v);
}
void dfs_4(graph &g, int v){
	if(f[v] == 1) return;
	f[v] = 1;
	for(edges::iterator i=g[v].begin(); i!=g[v].end(); ++i){
		dfs_4(g, *i);
	}
}
int count(){
	f.clear();
	f.resize(n);
	vi.clear();
	int t = 1;
	int res = 0;
	for(int i=0;i<n;++i){
		if(f[i] == 0){
			dfs(g, i);
		}
	}
	f.clear();
	f.resize(n);
	reverse(vi.begin(), vi.end());
	dag.clear();
	c.clear();
	c.resize(n);
	for(vector<int>::iterator i=vi.begin();i!=vi.end();++i){
		if(f[*i] == 0){
			dfs_2(gi, *i, res);
			++res;
		}
	}
	dag.resize(res);
	for(int i=0;i<res;++i){
		dag[i].clear();
	}
	for(int i=0;i<n;++i){
		for(vector<int>::iterator j=g[i].begin();j!=g[i].end();++j){
			if(c[i] != c[*j]){
				dag[c[i]].push_back(c[*j]);
			}
		}
	}
	f.clear();
	f.resize(res);
	vi.clear();
	for(int i=0;i<res;++i){
		if(f[i] == 0){
			dfs_3(dag, i);
		}
	}
	int cnt = 0;
	f.clear();
	f.resize(res);
	reverse(vi.begin(), vi.end());
	for(vector<int>::iterator i=vi.begin();i!=vi.end();++i){
		if(f[*i] == 0){
			dfs_4(dag, *i);
			++cnt;
		}
	}
	return cnt;
}
void solve(){
	create_squares();
	create_graph();
	printf("%d\n", count());
}
int main(){
	for(;;){
		scanf("%d%d", &n, &d);
		if(n == 0) return 0;
		for(int i=0;i<n;++i){
			for(int j=0;j<M;++j){
				int x, y;
				scanf("%d%d", &x, &y);
				tr[i][j] = P(x, y);
			}
			for(int j=0;j<M;++j){
				double d1, d2;
				d1 = abs(tr[i][(j+1)%M] - tr[i][j]);
				d2 = abs(tr[i][(j+2)%M] - tr[i][j]);
				if(abs(d1 - d2) < EPS){
					P t = tr[i][2];
					tr[i][2] = tr[i][j];
					tr[i][j] = t;
				}
			}
		}
		solve();
	}
}
accuracy: 1
time_ms: 40
memory_kb: 0
final_rank: 3

code_snippet: #include<complex>
#include<vector>
#include<iostream>
#include<stack>
#include<cmath>

enum CCW{FRONT=0x01,RIGHT=0x02,BACK=0x04,LEFT=0x08,OVER=0x10};
enum CIRCLE_RELATION{CIRCLE_SAME=0x01,CIRCLE_CONTAIN=0x02,
		     CIRCLE_NO_CROSS=0x04,CIRCLE_ONE_CROSS=0x08,
		     CIRCLE_ONE_INSIDE_CROSS=0x10,CIRCLE_TWO_CROSS=0x20};
#define sc second
#define fr first

#define REP(i,n) for(int i = 0; i < (int)(n); ++i)

using namespace std;

typedef double elem;
typedef complex<elem> point, vec;
typedef pair<point, point> line, hline, seg, pp;

const double infty = 1e40;
const double eps = 1e-8;
const double pi = acos(-1.0);
point base(0,0);

// oÍ
ostream &operator<<(ostream &os, const pair<point,point> &p){
  os << p.fr << "-" << p.sc;
  return os;
}

// lZ
inline elem sq(elem a){ return a*a; }
inline elem cq(elem a){ return a*a*a; }

// pxÏ·
elem rad(elem deg){ return (deg/180)*pi; }
elem deg(elem rad){ return (rad*180)/pi; }

// ®¬_Ìô¢AÈÇ
bool eq(elem a, elem b){ return abs(a-b) < eps; }
bool eqv(vec a, vec b){ return eq( abs(b-a),0); }

// _Iy[^
bool far(point a, point b){ return abs(b-a)>0; }
bool near(point a, point b){ return abs(b-a)<=0; }
elem dot(vec a, vec b){ return (a.real() * b.real() + a.imag() * b.imag() ); }
elem cross(vec a, vec b){ return ( a.real() * b.imag() - a.imag() * b.real() ); }

// a©çbÜÅvñèÌpxAàpA]ñ]
elem varg(vec a, vec b){
  elem ret=arg(a)-arg(b);
  if(ret<0)ret+=2*pi;
  if(ret>2*pi)ret-=2*pi;
  if(eq(ret,2*pi))ret=0;
  return ret;
}
elem varg2(vec a, vec b){
  elem ret = varg(a,b);
  if(ret>pi)return 2*pi-ret;
  return ret;
}
elem arg(vec a, vec b){ return acos( dot(a,b) / ( abs(a) * abs(b) ) ); }
point rot(point p, elem theta){ return p * polar((elem)1.0, theta); }
point rotdeg(point p, elem deg){ return p * polar((elem)1.0, rad(deg)); }
point proj(line l, point p){
  double t=dot(p-l.first,l.first-l.second)/abs(l.first-l.second);
  return l.first + t*(l.first-l.second);
}
point reflect(line l, point p){ return p+2.0*(proj(l,p)-p); }

// ñ_Ô£A¼üÆ_ÌÅZ£AüªÆ_ÌÅZ£
elem dist(point a, point b){ return abs(a-b); }
elem dist_l(line l, point x){ return abs(cross(l.sc-l.fr,x-l.fr)) / abs(l.sc-l.fr); }
elem dist_seg(seg s, point x)
{
  if( dot(s.sc-s.fr,x-s.fr)<0 ) return abs(x-s.fr);
  if( dot(s.fr-s.sc,x-s.sc)<0 ) return abs(x-s.sc);
  return dist_l(s,x);
}

// PÊxNgA@üxNgAPÊ@üxNg
vec uvec(vec a){ return a / abs(a); }
vec nmr(vec a){ return a * vec(0,-1); }
vec nml(vec a){ return a * vec(0,1); }
vec unmr(vec a){ return uvec( nmr(a) ); }
vec unml(vec a){ return uvec( nml(a) ); }

// ¼ðA½s»è
bool orth(point a1, point a2, point b1, point b2){ return eq( dot( a2 - a1, b2 - b1 ), 0 ); }
bool orth(vec v1, vec v2){ return eq( dot(v1, v2), 0 ); }
bool prll(point a1, point a2, point b1, point b2){ return eq( cross( a2 - a1, b2 - b1 ), 0 ); }
bool prll(vec v1, vec v2){ return eq( cross(v1, v2), 0 ); }

// CCW oXg¾ªA¸xÉæé
inline int ccw(const point &a, point b, point x){
  b -= a;
  x -= a;
  if( eq(cross(b,x),0.0) && dot(b,x) < 0 ) return BACK;
  if( eq(cross(b,x),0.0) && abs(b) < abs(x) ) return FRONT;
  if( eq(cross(b,x),0.0) ) return OVER;
  if( cross(b,x) > 0 ) return LEFT;
  if( cross(b,x) < 0 ) return RIGHT;
}

// üªg£
line expandLine(line l, elem mag){
  line ret = l;
  vec vf(l.first - l.second);
  vec vs(l.second - l.first);
  ret.first = l.second + mag * vf;
  ret.second = l.first + mag * vs;
  return ret;
}

// üªÌð·»è
inline bool intersectedSS(const seg &a, const seg &b)
{
  int cwaf=ccw(a.fr,a.sc,b.fr);
  int cwbf=ccw(b.fr,b.sc,a.fr);
  int cwas=ccw(a.fr,a.sc,b.sc);
  int cwbs=ccw(b.fr,b.sc,a.sc);
  if( cwaf==OVER || cwas==OVER || cwbf==OVER || cwbs==OVER ) return true;
  return ( cwaf | cwas ) == (LEFT|RIGHT) && ( cwbf | cwbs ) == (LEFT|RIGHT);
}

// ¼üÌð·»è
bool intersectedLL(line a, line b){ return !eq( cross(a.sc-a.fr,b.sc-b.fr), 0.0 ); }

// ð_vZ
point intersectionSS(seg a, seg b)
{
  elem d1 = dist_l(b,a.fr);
  elem d2 = dist_l(b,a.sc);
  return a.fr + ( d1 / (d1 + d2 ) ) * (a.sc-a.fr);
}
point intersectionLL(line a, line b)
{
  vec va = a.sc - a.fr;
  vec vb = b.sc - b.fr;
  return a.fr + va * ( cross(vb, b.fr - a.fr) / cross(vb,va) );
}

// üªð_êÅ
bool intersectionLL(line a, line b, point &ret){
  return intersectedLL( a, b ) ? ret = intersectionLL( a, b ), true : false;
}
bool intersectionLH(line a, hline b, point &ret){
  point tmp;
  return intersectionLL(a,b,tmp) ? ( ccw(b.fr,b.sc,tmp)&(OVER|FRONT) ? ret=tmp, true : false ) : false;
}
bool intersectionLS(line l, seg s, point &ret){
  point tmp;
  return intersectionLL(l,s,tmp) ? ( ccw(s.fr,s.sc,tmp)&OVER ? ret=tmp, true : false ) : false;
}
bool intersectionHH(hline a, hline b, point &ret){
  point tmp;
  return intersectionLL(a,b,tmp) ? ( ccw(a.fr,a.sc,tmp)&(OVER|FRONT)&&ccw(b.fr,b.sc,tmp)&(OVER|FRONT) ? ret = tmp, true : false ) : false;
}
bool intersectionHS(hline a, seg s, point &ret){
  point tmp;
  return intersectionLS(a,s,tmp) ? ( ccw(a.fr,a.sc,tmp)&(OVER|FRONT) ? ret = tmp, true : false ) : false;
}
bool intersectionSS(seg a, seg b, point &ret){
  return intersectedSS(a,b) ? ret = intersectionSS(a,b), true : false;
}

/* Op` */
struct triangle{
  vector<point> p;
  triangle():p(3,point(0,0)){}
  triangle(point a,point b,point c){p.push_back(a);p.push_back(b);p.push_back(c);}
  bool inside(const point &t)const{
    int ccw01=ccw(p[0],p[1],t),ccw02=ccw(p[1],p[2],t),ccw03=ccw(p[2],p[0],t);
    return ccw01==ccw02&&ccw02==ccw03;
  }
  bool contain(const point &t)const{
    int ccw01=ccw(p[0],p[1],t),ccw02=ccw(p[1],p[2],t),ccw03=ccw(p[2],p[0],t);
    if((ccw01|ccw02|ccw03)&OVER)return true;
    else return ccw01==ccw02&&ccw02==ccw03;
  }
};

/* é` */
struct rectangle{
  vector<point> p;
  rectangle():p(4,point(0,0)){}
  rectangle(point a, point b, point c, point d){
    p.push_back(a);  p.push_back(b);  p.push_back(c);  p.push_back(d);
  }
  bool inside(const point &t)const{
    int ccw01=ccw(p[0],p[1],t),ccw02=ccw(p[1],p[2],t),ccw03=ccw(p[2],p[0],t);
    return ccw01==ccw02&&ccw02==ccw03;
  }
  bool contain(const point &t)const{
    int ccw01=ccw(p[0],p[1],t),ccw02=ccw(p[1],p[2],t),ccw03=ccw(p[2],p[3],t),ccw04=ccw(p[3],p[0],t);
    if((ccw01|ccw02|ccw03|ccw04)&OVER)return true;
    else return ccw01==ccw02&&ccw02==ccw03&&ccw03==ccw04;
  }
  bool rayReach(const triangle &t){ // t : traignle
    for(int i = 0; i < (int)t.p.size(); ++i){
      if( this->contain(t.p[i]) ) return true;
    }
    for(int i = 0; i < 4; ++i){
      seg s(p[i],p[(i+1)%4]);
      for(int j = 0; j < (int)t.p.size(); ++j){
	seg ss(t.p[j],t.p[(j+1)%t.p.size()]);
	if( intersectedSS( s, ss ) ) return true;
      }
    }
    return false;
  }
};

rectangle touch(triangle t, elem d)
{
  rectangle ret;
  elem da=abs(t.p[0]-t.p[1]);
  elem db=abs(t.p[1]-t.p[2]);
  elem dc=abs(t.p[2]-t.p[0]);
  
  if(eq(da,db)){
    vec v=d*uvec( t.p[1] - (t.p[2]+t.p[0])/2.0 );
    ret.p[0]=t.p[2]+v;
    ret.p[1]=t.p[2];
    ret.p[2]=t.p[0];
    ret.p[3]=t.p[0]+v;
  }else if(eq(da,dc)){
    vec v=d*uvec( t.p[0] - (t.p[1]+t.p[2])/2.0 );
    ret.p[0]=t.p[1]+v;
    ret.p[1]=t.p[1];
    ret.p[2]=t.p[2];
    ret.p[3]=t.p[2]+v;
  }else if(eq(db,dc)){
    vec v=d*uvec( t.p[2] - (t.p[0]+t.p[1])/2.0 );
    ret.p[0]=t.p[0]+v;
    ret.p[1]=t.p[0];
    ret.p[2]=t.p[1];
    ret.p[3]=t.p[1]+v;
  }
  return ret;
}

struct Node{
  vector<int> con;
};

typedef vector<Node> Graph;

void visit(const Graph &g, int v, vector< vector<int> > &scc,
	   stack<int> &S, vector<int> &inS,
	   vector<int> &low, vector<int> &num, int &time)
{
  low[v] = num[v] = ++time;
  S.push(v);
  inS[v]=1;
  for(int i = 0; i < (int)g[v].con.size(); ++i){
    int w=g[v].con[i];
    if(num[w]==0){
      visit(g,w,scc,S,inS,low,num,time);
      low[v]=min(low[v],low[w]);
    }else if(inS[w])
      low[v]=min(low[v],num[w]);
  }
  if(low[v]==num[v]){
    scc.push_back(vector<int>());
    while(true){
      int w=S.top(); S.pop(); inS[w]=0;
      scc.back().push_back(w);
      if( v == w ) break;
    }
  }
}
void stronglyConnectedComponents(const Graph &g, vector< vector<int> > &scc)
{
  int n = g.size();
  vector<int> num(n),low(n);
  stack<int> S;
  vector<int> inS(n);
  int time=0;
  for(int i=0;i<n;++i){
    if(num[i]==0)
      visit(g,i,scc,S,inS,low,num,time);
  }
}

int solve(const vector<triangle> &vt, elem d)
{
  Graph G;

  for(int i = 0; i < (int)vt.size(); ++i){
    Node node;
    for(int j = 0; j < (int)vt.size(); ++j){
      if( i != j ){
	rectangle R = touch(vt[i],d);
	if( R.rayReach( vt[j] ) ){
	  node.con.push_back(j);
	}
      }else
	node.con.push_back(j);
    }
    G.push_back(node);
  }
  
  vector< vector<int> > scc;
  stronglyConnectedComponents( G, scc );

  int in[scc.size()];
  for(int i = 0; i < (int)scc.size(); ++i){
    in[i] = 0;
  }
  Graph DAG;
  for(int i = 0; i < (int)scc.size(); ++i){
    Node node;
    for(int ii = 0; ii < (int)scc[i].size(); ++ii){
      int from = scc[i][ii];
      for(int j = 0; j < (int)scc.size(); ++j){
	if(i!=j){
	  for(int jj = 0; jj < (int)scc[j].size(); ++jj){
	    int to = scc[j][jj];
	    for(int k = 0; k < (int)G[from].con.size(); ++k){
	      if( G[from].con[k] == to ){
		node.con.push_back(j);
		in[j]++;
		goto next;
	      }
	    }
	  }
	next:;
	}
      }
    }
    DAG.push_back(node);
  }

  /*
  for(int i = 0; i < (int)DAG.size(); ++i){
    printf("%d : ", i );
    for(int j = 0; j < (int)DAG[i].con.size(); ++j){
      printf("%d ", DAG[i].con[j] );
    }
    printf("\n");
  }
  */

  int ret = 0;
  for(int i = 0; i < (int)DAG.size(); ++i){
    if( in[i] == 0 ) ++ret;
  }
  return ret;
}

int main(){
  while(true){
    int n;
    elem d;
    vector<triangle> vt;
    scanf("%d%lf", &n, &d);
    if(n==0)break;
    for(int i = 0; i < n; ++i){
      double x1,y1,x2,y2,x3,y3;
      scanf("%lf%lf%lf%lf%lf%lf", &x1, &y1, &x2, &y2, &x3, &y3);
      point ta(x1,y1),tb(x2,y2),tc(x3,y3);
      vt.push_back(triangle(ta,tb,tc));
    }
    int res = solve( vt, d );
    printf("%d\n", res);
  }
  return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 0
final_rank: 1

code_snippet: #include<iostream>
#include<map>
#include<complex>
#include<queue>
#include<vector>
#include<algorithm>
#include<cassert>
#include<set>
#include<cassert>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(c)   (c).begin(),(c).end()
#define pb push_back
#define mp make_pair

const int N = 100;

//graph part
vector<int> edge[N];
bool vis[N];

int ord;
vector<int> inedge[N];
vector<int> redge[N];
int component[N];
struct PO{
  int order,num;
};
PO postorder[N];

bool cmp(const PO a,const PO b){
  return a.order > b.order;
}

void sccdfs(int now){
  vis[now]=1;
  rep(i,inedge[now].size()){
    int next=inedge[now][i];
    if (!vis[next])sccdfs(next);
  }
  postorder[now].order=ord++;
  postorder[now].num=now;
}

void sccbfs(int ini,int comp){
  queue<int> Q;
  Q.push(ini);
  vis[ini]=true;
  component[ini]=comp;
  while(!Q.empty()){
    int now=Q.front();Q.pop();
    component[now]=comp;
    rep(i,redge[now].size()){
      int next=redge[now][i];
      if (!vis[next])Q.push(next),vis[next]=true;
    }
  }
}

int scc(int n,map<int,int> &M){
  ord=0;
  rep(i,n)vis[i]=false;
  rep(i,n){
    if (!vis[i])sccdfs(i);
  }
  int cnt=0;
  rep(i,n)vis[i]=false;
  sort(postorder,postorder+n,cmp);
  rep(i,n){
    int now = postorder[i].num;
    if (vis[now])continue;
    sccbfs(now,cnt);
    cnt++;
  }
  rep(i,n)M[i]=component[i];
  return cnt;
}

void tsort(int now,vector<int> &a){
  if (vis[now])return;
  vis[now]=true;
  rep(i,edge[now].size())tsort(edge[now][i],a);
  a.pb(now);
}

void dfs(int now){
  if (vis[now])return;
  vis[now]=true;
  rep(i,edge[now].size())dfs(edge[now][i]);
}

int solve(int n){
  map<int,int> M;
  int tmpn=scc(n,M);
  rep(i,n){
    int me=M[i];
    rep(j,inedge[i].size()){
      int you=M[inedge[i][j]];
      edge[me].pb(you);
    }
  }

  n=tmpn;
  vector<int> in;
  rep(i,n)vis[i]=false;
  rep(i,n){
    if (!vis[i])tsort(i,in);
  }
  reverse(ALL(in));
  int cnt=0;
  rep(i,n)vis[i]=false;
  rep(i,in.size()){
    if (!vis[in[i]])dfs(in[i]),cnt++;
  }
  return cnt;
}

//geometry part
typedef complex<double> P;
const double eps = 1e-1;
vector<P> getpolygon(vector<P> a,double d){
  int in[3]={0,1,2};
  vector<P> ret;
  do{
    if (fabs(abs(a[in[2]]-a[in[1]])-abs(a[in[2]]-a[in[0]])) < eps){
      P mid =(a[in[0]]+a[in[1]])/2.;
      P tmp=a[in[2]]-mid;
      tmp/=abs(tmp);
      tmp*=d;
      ret.pb(a[in[0]]);
      ret.pb(a[in[1]]);
      ret.pb(a[in[1]]+tmp);
      ret.pb(a[in[0]]+tmp);
      return ret;
    }
  }while(next_permutation(in,in+3));
  assert(false);
  return ret;
}

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

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

double distance_ls_p(P a,P b,P c){
  if (dot(b-a,c-a) < eps)return abs(c-a);
  if (dot(a-b,c-b) < eps)return abs(c-b);
  return abs( cross(b-a,c-a))/abs(b-a);
}

bool isp(P a,P b,P c){
  return ( abs(a-c)+abs(b-c) < abs(a-b)+eps);
}

bool is_in(vector<P> in,P a){
  int cnt =0;
  int n = in.size();
  rep(i,n){
    P cur = in[i]-a,next=in[(i+1)%n]-a;
    if (cur.imag() > next.imag())swap(cur,next);
    if (cur.imag()<0 && 0<=next.imag() &&
        cross(next,cur)>=0)cnt++;
    if (isp(in[i],in[(i+1)%n],a))return true;
  }

  if (cnt %2 == 1)return true;
  else return false;
}

bool is_intersected_ls(P a1,P a2,P b1,P b2){
  if ( isp(a1,a2,b1))return true;
  if ( isp(a1,a2,b2))return true;
  if ( isp(b1,b2,a1))return true;
  if ( isp(b1,b2,a2))return true;
  if (  ( cross(a2-a1,b1-a1) * cross(a2-a1,b2-a1)<-eps ) && //-EPS
        ( cross(b2-b1,a1-b1)*cross(b2-b1,a2-b1)  <-eps))return true;
  else return false;
}

bool is_intersected_polygon(vector<P> a,vector<P> b){
  int n = a.size();
  int m = b.size();
  rep(i,a.size()){
    rep(j,b.size()){
      if (is_intersected_ls(a[i],a[(i+1)%n],b[j],b[(j+1)%m]))
        return true;
    }
  }
  rep(i,b.size()){
    if (is_in(a,b[i]))return true;
  }
  return false;
}

void makegraph(int n,vector<P> *sq,vector<P> *tri){
  rep(i,n){
    rep(j,n){
      if (i == j)continue;
      if (is_intersected_polygon(sq[i],tri[j])){
        inedge[i].pb(j);
        redge[j].pb(i);
      }
    }
  }
}

main(){
  int n;
  double d;
  while(cin>>n>>d && n){
    rep(i,n){
      edge[i].clear();
      inedge[i].clear();
      redge[i].clear();
    }
    vector<P> in[n];
    vector<P> sq[n];
    rep(i,n){
      rep(j,3){
        P tmp;cin>>tmp.real()>>tmp.imag();in[i].pb(tmp);
      }
      sq[i]=getpolygon(in[i],d);
    }
    makegraph(n,sq,in);
    cout << solve(n) << endl;
  }
  return false;
}
accuracy: 1
time_ms: 60
memory_kb: 1020
final_rank: 16