const int MAXN = 100005;
int n, m, u, v, w, tot, cnt, head[MAXN];
struct node {
int next, to, val;
} edge[MAXN << 1];
void add(int u, int v, int w) {
edge[++tot].next = head[u];
edge[tot].to = v;
edge[tot].val = w;
head[u] = tot;
}
struct data {
int x, y, z;
data() { x = y = z = 0; }
data(int _x, int _y, int _z) { x = _x, y = _y, z = _z; }
friend data operator + (data a, data b) {
return data(a.x + b.x, a.y + b.y, a.z + b.z);
}
friend data operator - (data a, data b) {
return data(a.x - b.x, a.y - b.y, a.z - b.z);
}
friend data operator * (data a, int b) {
return data(a.x * b, a.y * b, a.z * b);
}
friend data operator / (data a, int b) {
return data(a.x / b, a.y / b, a.z / b);
}
} a[MAXN];
data sum[MAXN];
int fa[MAXN], size[MAXN];
int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
void merge(int x, int y) {
int fx = find(x), fy = find(y);
if (fx == fy) return;
if (size[fx] > size[fy]) swap(fx, fy);
fa[fx] = fy;
size[fy] += size[fx];
}
bool cmp(node a, node b) {
return a.val < b.val;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d%d%d", &a[i].x, &a[i].y, &a[i].z);
for (int i = 1; i <= m; i++) scanf("%d%d%d", &u, &v, &w), add(u, v, w), add(v, u, w);
for (int i = 1; i <= n; i++) sum[i] = a[i] + a[i] + a[i];
for (int i = 1; i <= n; i++) sort(sum + i, sum + i + 3);
for (int i = 1; i <= n; i++) {
for (int j = head[i]; j; j = edge[j].next) {
int v = edge[j].to;
merge(i, v);
}
}
sort(edge + 1, edge + 1 + tot, cmp);
for (int i = 1; i <= tot; i++) {
int u = edge[i].to, v = edge[i].val;
if (find(u) == find(v)) continue;
merge(u, v);
}
for (int i = 1; i <= n; i++) cnt = max(cnt, size[i]);
printf("%d\n", cnt);
return 0;
}
