#include <fstream>
#include <vector>
#include <algorithm>
#include <cmath>
#define INF 1000000000
#define coordMax 1000001
#define nMax 101
#define edgesMax 10001
#define pb push_back
#define mkp make_pair
#define x first
#define y second
using namespace std;
ifstream fin("elicoptere.in");
ofstream fout("elicoptere.out");
int op, n, conex[nMax], viz[nMax], heap[nMax], poz[nMax], nrEl, nrConex;
double distMax, distApm[nMax];
pair<double, double> tr[nMax][4];
vector<pair<int, double> > G[nMax];
double dist(double x1, double y1, double x2, double y2)
{
return sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
double determinant(double x1, double y1, double x2, double y2, double x3, double y3)
{
return x1*y2+y1*x3+x2*y3-y2*x3-y1*x2-x1*y3;
}
void upDateHeap(int pozi)
{
int po;
while(pozi/2)
{
po=pozi/2;
if(distApm[heap[po]]>distApm[heap[pozi]])
{
swap(heap[po], heap[pozi]);
swap(poz[heap[po]], poz[heap[pozi]]);
pozi=po;
}
else
break;
}
}
void insertHeap(int node)
{
heap[++nrEl]=node;
poz[node]=nrEl;
upDateHeap(poz[node]);
}
void downDateHeap(int pozi)
{
int po;
while(pozi*2<=nrEl)
{
po=pozi*2;
if(po+1<=nrEl && distApm[heap[po]]>distApm[heap[po+1]])
po++;
if(distApm[heap[po]]<distApm[heap[pozi]])
{
swap(heap[po], heap[pozi]);
swap(poz[heap[po]], poz[heap[pozi]]);
pozi=po;
}
else
break;
}
}
void inApm(int node)
{
for(vector<pair<int, double> >::iterator it=G[node].begin(); it!=G[node].end(); it++)
{
int fiu=it->first;
double cost=it->second;
distApm[fiu]=min(distApm[fiu], cost);
if(viz[fiu]==0)
{
viz[fiu]=1;
insertHeap(fiu);
}
}
}
int extractHeap(int pozi)
{
int node=heap[pozi];
swap(heap[pozi], heap[nrEl]);
swap(poz[heap[pozi]], poz[heap[nrEl]]);
nrEl--;
downDateHeap(1);
poz[node]=0;
return node;
}
void dfs(int node)
{
viz[node]=1;
conex[nrConex]++;
for(vector<pair<int, double> >::iterator it=G[node].begin(); it!=G[node].end(); it++)
{
int fiu=it->first;
if(viz[fiu])
continue;
dfs(fiu);
}
}
pair<pair<double, double>, double> ecuatieDreapta(double x1, double y1, double x2, double y2)
{
pair<pair<double, double>, double> Sol;
Sol.x.x=x2-x1;
Sol.x.y=y1-y2;
Sol.y=x1*y2-y1*x2;
return Sol;
}
pair<double, double> intersectDrepte(pair<pair<double, double>, double> ec1, pair<pair<double, double>, double> ec2)
{
pair<double, double> Sol;
if(ec1.x.x==0)
swap(ec1, ec2);
Sol.x=(ec2.x.x*ec1.y-ec1.x.x*ec2.y)/(ec1.x.x*ec2.x.y-ec1.x.y*ec2.x.x);
Sol.y=(-ec1.x.y*Sol.x-ec1.y)/ec1.x.x;
return Sol;
}
int main()
{
fin>>op>>n>>distMax;
for(int i=1; i<=n; i++)
{
for(int j=0; j<3; j++)
fin>>tr[i][j].x>>tr[i][j].y;
tr[i][3]=tr[i][0];
}
for(int i=1; i<=n; i++)
{
for(int j=0; j<3; j++)
{
pair<pair<double, double>, double> ecVert=ecuatieDreapta(tr[i][j].x, tr[i][j].y, tr[i][j].x, tr[i][j].y+1);
pair<pair<double, double>, double> ecOriz=ecuatieDreapta(tr[i][j].x, tr[i][j].y, tr[i][j].x+1, tr[i][j].y);
for(int t=1; t<=n; t++)
{
if(i!=t)
{
for(int k=0; k<3; k++)
{
double distantaMin=INF;
pair<pair<double, double>, double> ecDr=ecuatieDreapta(tr[t][k].x, tr[t][k].y, tr[t][k+1].x, tr[t][k+1].y);
if(tr[t][k].x!=tr[t][k+1].x || (tr[t][k].x==tr[t][k+1].x && tr[t][k].x==tr[i][j].x))//intersectia cu verticala
{
pair<double, double> pctIntersect=intersectDrepte(ecDr, ecVert);
if(tr[i][j].x==tr[t][k].x && tr[i][j].x==tr[t][k+1].x)
{
if(tr[t][k].y<tr[i][j].y)
pctIntersect=mkp(tr[t][k].x, tr[t][k+1].y);
else
pctIntersect=mkp(tr[t][k].x, tr[t][k].y);
double distanta=dist(tr[i][j].x, tr[i][j].y, pctIntersect.x, pctIntersect.y);
distantaMin=min(distantaMin, distanta);
}
else
{
double det1=determinant(tr[i][j].x, coordMax, tr[i][j].x, 0, tr[t][k].x, tr[t][k].y);
double det2=determinant(tr[i][j].x, coordMax, tr[i][j].x, 0, tr[t][k+1].x, tr[t][k+1].y);
if((det1<=0 && det2>=0) || (det1>=0 && det2<=0))
{
double distanta=dist(tr[i][j].x, tr[i][j].y, pctIntersect.x, pctIntersect.y);
distantaMin=min(distantaMin, distanta);
}
}
}
if(tr[t][k].y!=tr[t][k+1].y || (tr[t][k].y==tr[t][k+1].y && tr[t][k].y==tr[i][j].y))//intersectia cu orizontala
{
pair<double, double> pctIntersect=intersectDrepte(ecDr, ecOriz);
if(tr[i][j].y==tr[t][k].y && tr[i][j].y==tr[t][k+1].y)
{
if(tr[t][k].x<tr[i][j].x)
pctIntersect=mkp(tr[t][k+1].x, tr[t][k].y);
else
pctIntersect=mkp(tr[t][k].x, tr[t][k].y);
double distanta=dist(tr[i][j].x, tr[i][j].y, pctIntersect.x, pctIntersect.y);
distantaMin=min(distantaMin, distanta);
}
else
{
double det1=determinant(0, tr[i][j].y, coordMax, tr[i][j].y, tr[t][k].x, tr[t][k].y);
double det2=determinant(0, tr[i][j].y, coordMax, tr[i][j].y, tr[t][k+1].x, tr[t][k+1].y);
if((det1<=0 && det2>=0) || (det1>=0 && det2<=0))
{
double distanta=dist(tr[i][j].x, tr[i][j].y, pctIntersect.x, pctIntersect.y);
distantaMin=min(distantaMin, distanta);
}
}
}
if(distantaMin<=distMax)
{
G[i].pb(mkp(t, distantaMin));
G[t].pb(mkp(i, distantaMin));
}
}
}
}
}
}
if(op==1 || op==2)
{
for(int i=1; i<=n; i++)
{
if(viz[i]==0)
{
nrConex++;
dfs(i);
}
}
if(op==1)
{
int Sol=0;
for(int i=1; i<=nrConex; i++)
Sol+=conex[i]-1;
fout<<Sol;
return 0;
}
if(op==2)
{
int Sol=0;
for(int i=1; i<=nrConex; i++)
Sol+=conex[i]*(conex[i]-1)/2;
fout<<Sol;
return 0;
}
}
else
{
double Sol=0;
for(int i=1; i<=n; i++)
distApm[i]=INF;
for(int i=1; i<=n; i++)
{
if(viz[i]==0)
{
viz[i]=1;
distApm[i]=0;
inApm(i);
while(nrEl)
{
int node=extractHeap(1);
inApm(node);
Sol+=distApm[node];
for(vector<pair<int, double> >::iterator it=G[node].begin(); it!=G[node].end(); it++)
{
int fiu=it->first;
if(poz[fiu])
upDateHeap(poz[fiu]);
}
}
}
}
fout<<Sol;
}
}