#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = (a); i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()
#define ff first
#define ss second
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef unsigned long long ull;
typedef long double ld;
const int S = int(2e3)+100;
const ll INF = ll(1e9)+7;
const ll MOD = ll(1e9+7);
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
void print(vector <T> &v) {
	trav(x, v)
		cout << x << " ";
	cout << endl;
}

struct Dinic {
	struct Edge {
		int to, rev;
		ll c, oc;
		ll flow() { return max(oc - c, 0LL); } // if you need flows
	};
	vi lvl, ptr, q;
	vector<vector<Edge>> adj;
	Dinic(int n) : lvl(n), ptr(n), q(n), adj(n) {}
	void addEdge(int a, int b, ll c, int rcap = 0) {
		adj[a].push_back({b, sz(adj[b]), c, c});
		adj[b].push_back({a, sz(adj[a]) - 1, rcap, rcap});
	}
	ll dfs(int v, int t, ll f) {
		if (v == t || !f) return f;
		for (int& i = ptr[v]; i < sz(adj[v]); i++) {
			Edge& e = adj[v][i];
			if (lvl[e.to] == lvl[v] + 1)
				if (ll p = dfs(e.to, t, min(f, e.c))) {
					e.c -= p, adj[e.to][e.rev].c += p;
					return p;
				}
		}
		return 0;
	}
	ll calc(int s, int t) {
		ll flow = 0; q[0] = s;
		rep(L,0,31) do { // 'int L=30' maybe faster for random data
			lvl = ptr = vi(sz(q));
			int qi = 0, qe = lvl[s] = 1;
			while (qi < qe && !lvl[t]) {
				int v = q[qi++];
				trav(e, adj[v])
					if (!lvl[e.to] && e.c >> (30 - L))
						q[qe++] = e.to, lvl[e.to] = lvl[v] + 1;
			}
			while (ll p = dfs(s, t, LLONG_MAX)) flow += p;
		} while (lvl[t]);
		return flow;
	}
};

int n;
map <pii, ll> f, c;
vector <pii> pts;

int main()
{
	//freopen("stuff.in", "r", stdin);
	cin.sync_with_stdio(0); cin.tie(0);

	cin >> n;
	ll sum = 0;
	int cnt = 0;
	Dinic D(2*n + 2);
	rep(i, 0, n) {
		int x, y;
		ll w;
		cin >> x >> y >> w;
		c[{x, y}] = cnt++;
		pts.push_back({x, y});
		sum += w;
		D.addEdge(i, i+n, w);
		if((x&1) == 1 && (y&1) == 0)
			D.addEdge(2*n, i, INF);
		if((x&1) == 1 && (y&1) == 1)
			D.addEdge(i+n, 2*n+1, INF);
	}

	rep(i, 0, n) {
		int x = pts[i].ff, y = pts[i].ss;
		if((x&1) == 1 && (y&1) == 0) {
			if(c.count({x+1, y}))
				D.addEdge(i+n, c[{x+1, y}], INF);
			if(c.count({x-1, y}))
				D.addEdge(i+n, c[{x-1, y}], INF);
		} 
		if((x&1) == 0 && (y&1) == 0) {
			if(c.count({x, y+1}))
				D.addEdge(i+n, c[{x, y+1}], INF);
			if(c.count({x, y-1}))
				D.addEdge(i+n, c[{x, y-1}], INF);
		}
		if((x&1) == 0 && (y&1) == 1) {
			if(c.count({x+1, y}))
				D.addEdge(i+n, c[{x+1, y}], INF);
			if(c.count({x-1, y}))
				D.addEdge(i+n, c[{x-1, y}], INF);
		}
	}
	cout << sum - D.calc(2*n, 2*n+1) << endl;

	return 0;
}






