Language: C++

#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>

#define MAX_N (128)
#define EPS (0.01)
#define SQ(X) ((X) * (X))

using namespace std;

class Triangle {
	public:
        double x[3], y[3];
	    int no;
};

class Point {
    public:
    	double x, y;
        
	    Point Point::operator - (Point &a){
            Point ret;
		    ret.x = x - a.x;
		    ret.y = y - a.y;
		    return (ret);
	    }
};

vector<int> G[MAX_N];
vector<int> rG[MAX_N];
vector<int> compress[MAX_N];
vector<int> vs;
bool used[MAX_N];
bool group[MAX_N];
int cmp[MAX_N];
int N;

void addEdge(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 revDfs(int v, int k)
{
    used[v] = true;
    cmp[v] = k;
    for (int i = 0; i < rG[v].size(); i++){
        if (!used[rG[v][i]]){
            revDfs(rG[v][i], k);
        }
    }
}

int scc()
{
    int ret;
    memset(used, 0, sizeof(used));
    vs.clear();
    
    for (int i = 0; i < N; i++){
        if (!used[i]){
            dfs(i);
        }
    }
    
    memset(used, 0, sizeof(used));
    
    ret = 0;
    for (int i = vs.size() - 1; i >= 0; i--){
        if (!used[vs[i]]){
            revDfs(vs[i], ret++);
        }
    }
    
    for (int i = 0; i < N; i++){
        for (int j = 0; j < G[i].size(); j++){
            if (cmp[i] != cmp[G[i][j]]){
                compress[cmp[G[i][j]]].push_back(cmp[i]);
            }
        }
    }
    
    return (ret);
}

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

double getSize(Point a)
{
	return (sqrt(SQ(a.x) + SQ(a.y)));
}

bool checkCross(Point p1, Point p2, Point p3, Point p4)
{
    double check1 = (p2.x - p1.x) * (p4.y - p3.y) - (p2.y - p1.y) * (p4.x - p3.x);
    
    Point pq = p3 - p1;
    
    double check2 = (p4.y - p3.y) * pq.x - (p4.x - p3.x) * pq.y;
    double check3 = (p2.y - p1.y) * pq.x - (p2.x - p1.x) * pq.y;
    
    
    if (check1 > EPS){
        return (0 <= check3 / check1 && check3 / check1 <= 1 && 0 <= check2 / check1 && check2 / check1 <= 1);
    }
    
    return (fabs(check2) <= EPS && fabs(check3) <= EPS);
}

void judgeAdj(Triangle a, Triangle b, double dist)
{
	double len;
	Point p[4];
	
	len = 0.0;
	for (int i = 0; i < 3; i++){
		for (int j = i + 1; j < 3; j++){
			if (len < SQ(a.x[i] - a.x[j]) + SQ(a.y[i] - a.y[j])){
				len = SQ(a.x[i] - a.x[j]) + SQ(a.y[i] - a.y[j]);
				p[0].x = a.x[i], p[0].y = a.y[i];
				p[1].x = a.x[j], p[1].y = a.y[j];
			}
		}
	}
    //printf("%lf %lf %lf %lf\n", p[0].x, p[0].y, p[1].x, p[1].y);
	Point e, sa;
	
    e.x = 0, e.y = 1;
	sa = p[0] - p[1];
	double theta = acos(inProduct(e, sa) / (getSize(e) * getSize(sa)));
    theta = min(theta, M_PI - theta);
	//printf("theta = %lf\n", theta);
    
	p[2].x = p[0].x + dist * cos(theta), p[2].y = p[0].y + dist * sin(theta);
	p[3].x = p[1].x + dist * cos(theta), p[3].y = p[1].y + dist * sin(theta);
	
	bool cross = false;
	
	for (int i = 0; i < 3; i++){
		for (int j = i + 1; j < 3; j++){
            Point k[2];
            k[0].x = b.x[i], k[0].y = b.y[i];
            k[1].x = b.x[j], k[1].y = b.y[j];
			cross |= checkCross(k[0], k[1], p[0], p[1]);
			cross |= checkCross(k[0], k[1], p[0], p[2]);
			cross |= checkCross(k[0], k[1], p[1], p[3]);
			cross |= checkCross(k[0], k[1], p[2], p[3]);
		}
	}
	
	if (cross == true){
        //printf("hoge, %d, %d\n", a.no, b.no);
		addEdge(a.no, b.no);
	}
	
}

int main()
{
	int n, d;
	Triangle data[128];
	
	while (1){
		
		scanf("%d %d", &n, &d);
		
        N = n;
		if (n + d == 0){
			break;
		}
		
		for (int i = 0; i < n; i++){
			data[i].no = i;
			for (int j = 0; j < 3; j++){
				scanf("%lf%lf", &data[i].x[j], &data[i].y[j]);
			}
		}
		
        for (int i = 0; i < n; i++){
            G[i].clear();
            rG[i].clear();
            compress[i].clear();
        }
        
		for (int i = 0; i < n; i++){
			for (int j = 0; j < n; j++){
                if (i != j){
    				judgeAdj(data[i], data[j], d);
                }
			}
		}
		
		int k = scc();
    	
    	int ans = 0;
    	memset(used, 0, sizeof(used));
    	
    	for (int i = 0; i < k; i++){
        	if (compress[i].size() == 0){
        	    ans++;
        	}
    	}
    	
    	printf("%d\n", ans);
	}
	
	return (0);
}

Compiler output:
a.cc:22:19: error: extra qualification 'Point::' on member 'operator-' [-fpermissive]
   22 |             Point Point::operator - (Point &a){
      |                   ^~~~~
a.cc: In function 'int scc()':
a.cc:70:5: error: 'memset' was not declared in this scope
   70 |     memset(used, 0, sizeof(used));
      |     ^~~~~~
a.cc:5:1: note: 'memset' is defined in header '<cstring>'; this is probably fixable by adding '#include <cstring>'
    4 | #include <algorithm>
  +++ |+#include <cstring>
    5 | 
a.cc: In function 'int main()':
a.cc:212:9: error: 'memset' was not declared in this scope
  212 |         memset(used, 0, sizeof(used));
      |         ^~~~~~
a.cc:212:9: note: 'memset' is defined in header '<cstring>'; this is probably fixable by adding '#include <cstring>'