#include <iostream>
#include <map>
#include <vector>
#include <tuple>
#include <algorithm>
using namespace std;
const int maxn = 3e6 + 10;
const int dx[] = {1, 1, 1, 0, 0, -1, -1, -1};
const int dy[] = {1, 0, -1, 1, -1, 1, 0, -1};
int n, m, k, tot, top, cnt, head, tail, q[maxn], f[maxn], low[maxn], dfn[maxn], stk[maxn], deg[maxn], scc[maxn];
bool val[maxn], instack[maxn];
vector<int> e[maxn], g[maxn];
map<pair<int, int>, int> id;
void tarjan(int u) {
dfn[u] = low[u] = ++tot; instack[u] = true; stk[++top] = u;
for (int v : e[u])
if (!dfn[v]) tarjan(v), low[u] = min(low[u], low[v]);
else if (instack[v]) low[u] = min(low[u], dfn[v]);
if (dfn[u] == low[u]) {
scc[u] = ++cnt; val[cnt] = u <= k;
while (stk[top] != u)
val[scc[stk[top]] = cnt] += stk[top] <= k, instack[stk[top--]] = false;
instack[stk[top--]] = false;
}
}
int main() {
ios::sync_with_stdio(false);
cin >> k >> n >> m;
vector<tuple<int, int, int> > G(k);
for (auto& [x, y, t] : G)
cin >> x >> y >> t, id[{x, y}] = ++tot,
e[k + x].push_back(tot), e[k + n + y].push_back(tot);
for (auto [x, y, t] : G) {
int cur = id[{x, y}];
if (t == 1) e[cur].push_back(k + x);
else if (t == 2) e[cur].push_back(k + n + y);
else for (int d = 0; d < 8; d++) {
int nx = x + dx[d], ny = y + dy[d];
if (id.count({nx, ny}))
e[cur].push_back(id[{nx, ny}]);
}
}
for (int u = 1; u <= n + m + k; u++) if (!dfn[u]) tarjan(u);
for (int u = 1; u <= n + m + k; u++)
for (int v : e[u]) if (scc[u] != scc[v])
g[scc[u]].push_back(scc[v]), ++deg[scc[v]];
for (int u = 1; u <= cnt; u++) if (deg[u] == 0) q[tail++] = u, f[u] = val[u];
while (head < tail) {
int u = q[head++];
for (int v : g[u]) {
f[v] = max(f[v], f[u] + val[v]);
if (--deg[v] == 0) q[tail++] = v;
}
}
cout << *max_element(f + 1, f + cnt + 1) << '\n';
return 0;
}