#include<bits/stdc++.h>
#define mxn 2100005
using namespace std;
int in[mxn], ig[mxn], dfn[mxn], low[mxn], col[mxn], f[mxn], vl[mxn];
int n, m, r, c, a1, a2, cnt, ign;
bool vis[mxn];
vector<int> G[mxn], NG[mxn];
stack<int> s;
queue<int> q;
map<pair<int, int>, int> ing;
struct node{
int x, y, op;
}p[mxn];
void tarjan(int u){
dfn[u] = low[u] = ++cnt;
s.push(u);
vis[u] = 1;
for (auto &v : G[u]){
if (!dfn[v]){
tarjan(v);
low[u] = min(low[u], low[v]);
}else if (vis[v])
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]){
while (!s.empty()){
int v = s.top();
s.pop();
vis[v] = 0;
col[v] = u;
if (v > r + c)
vl[u]++;
if (u == v)
break;
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> m >> r >> c;
n = m + r + c;
for (int i = 1; i <= m; i++){
cin >> p[i].x >> p[i].y >> p[i].op;
ing[make_pair(p[i].x, p[i].y)] = i + r + c;
}
for (int i = 1; i <= m; i++){
if (p[i].op == 1){
G[p[i].y + r].push_back(i + r + c);
G[p[i].x].push_back(i + r + c);
G[i + r + c].push_back(p[i].x);
}else if (p[i].op == 2){
G[p[i].y + r].push_back(i + r + c);
G[p[i].x].push_back(i + r + c);
G[i + r + c].push_back(p[i].y + r);
}else{
G[p[i].y + r].push_back(i + r + c);
G[p[i].x].push_back(i + r + c);
for (int j = p[i].x - 8; j <= p[i].x + 8; j++)
for (int k = p[i].y - 8; k <= p[i].y + 8; k++){
if(ing[make_pair(j, k)])
G[i + r + c].push_back(ing[make_pair(j, k)]);
}
}
}
for (int i = 1; i <= n; i++)
if (!dfn[i])
tarjan(i);
for (int i = 1; i <= n; i++)
for (auto v : G[i]){
if (col[i] == col[v])
continue;
NG[col[i]].push_back(col[v]);
in[col[v]]++;
}
for (int i = 1; i <= n; i++){
if (!in[i] && col[i] == i){
q.push(i);
f[i] = vl[i];
}
}
while (!q.empty()){
int u = q.front();
q.pop();
for (auto v : NG[u]){
f[v] = max(f[v], f[u] + vl[v]);
in[v]--;
if (!in[v])
q.push(v);
}
}
int ans = 0;
for (int i = 1; i <= n; i++){
ans = max(ans, f[i]);
}
cout << ans;
}