Problem: At the foot of Liyushan Mountain, n tents will be carefully arranged to provide accommodation for those who are willing to experience the joy of approaching nature, the tranquility of the night, and the bright starry sky.

The i-th tent is located at the point of (x_i, y_i) and has a weight of w_i. A tent is important if and only if both x_i and y_i are even. You need to remove some tents such that for each remaining important tent (x, y), there do not exist 3 other tents (x'_1, y'_1), (x'_2, y'_2) and (x'_3, y'_3) such that both conditions are true: 

  1. |x'_j-x|, |y'_j - y|≤ 1 for all j ∈ \{1, 2, 3\}, and 
  2. these four tents form a parallelogram (or a rectangle) and one of its sides is parallel to the x-axis. 



Please maximize the sum of the weights of the tents that are not removed. Print the maximum value.

Input

The first line contains a single integer n (1≤ n≤ 1 000), representing the number of tents.

Each of the next n lines contains three integers x_i, y_i and w_i (-10^9≤ x_i,y_i ≤ 10^9, 1≤ w_i≤ 10^9), representing the coordinate of the i-th tent and its weight. No two tents are located at the same point.

Output

A single integer — the maximum sum of the weights of the remaining tents.

Examples

Input


5
0 0 4
0 1 5
1 0 3
1 1 1
-1 1 2


Output


12


Input


32
2 2 1
2 3 1
3 2 1
3 3 1
2 6 1
2 5 1
3 6 1
3 5 1
2 8 1
2 9 1
1 8 1
1 9 1
2 12 1
2 11 1
1 12 1
1 11 1
6 2 1
7 2 1
6 3 1
5 3 1
6 6 1
7 6 1
5 5 1
6 5 1
6 8 1
5 8 1
6 9 1
7 9 1
6 12 1
5 12 1
6 11 1
7 11 1


Output


24

Note

Here is an illustration of the second example. Black triangles indicate the important tents. This example also indicates all 8 forbidden patterns.

<image>

Solution (in CPP):

Solution:
/*{{{*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<iostream>
#include<sstream>
#include<set>
#include<map>
#include<queue>
#include<bitset>
#include<vector>
#include<limits.h>
#include<assert.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define REP(I, N) for (int I = 0; I < (N); ++I)
#define REPP(I, A, B) for (int I = (A); I < (B); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORS(I, S) for (int I = 0; S[I]; ++I)
#define RS(X) scanf("%s", (X))
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
#define MP make_pair
#define PB emplace_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL,LL> PLL;
typedef vector<PLL> VPLL;
template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(int64_t &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
template<class T> void _W(const T &x) { cout << x; }
void _W(const int &x) { printf("%d", x); }
void _W(const int64_t &x) { printf("%lld", x); }
void _W(const double &x) { printf("%.16f", x); }
void _W(const char &x) { putchar(x); }
void _W(const char *x) { printf("%s", x); }
template<class T,class U> void _W(const pair<T,U> &x) {_W(x.F); putchar(' '); _W(x.S);}
template<class T> void _W(const vector<T> &x) { for (auto i = x.begin(); i != x.end(); _W(*i++)) if (i != x.cbegin()) putchar(' '); }
void W() {}
template<class T, class... U> void W(const T &head, const U &... tail) { _W(head); putchar(sizeof...(tail) ? ' ' : '\n'); W(tail...); }
#ifdef HOME
 #define DEBUG(...) {printf("[DEBUG] ");W(__VA_ARGS__);}
#else
 #define DEBUG(...)
#endif
int MOD = 1e9+7;
void ADD(LL& x,LL v){x=(x+v)%MOD;if(x<0)x+=MOD;}
/*}}}*/
const int SIZE = 1<<20;
#define FN 500010
#define FM 2000010
#define INF 1000000000000000
struct E {
    int k;
    long long c;
    E() {}
    E( int _k, long long _c ) : k(_k), c(_c) {}
} es[FM];

struct Flow {
    int n, m, dis[FN];
    int qq[FN], qr, ql;
    int ptr[FN];
    vector<int> e[FN];
    void init( int _n ) {
        n = _n; m=0;
        for (int i = 0; i < n; i++) {
            vector<int> tmp;
            e[i].swap(tmp);
        }
    }
    void add_edge(int a, int b, long long c) {
        e[a].push_back(m); es[m]=E(b, c); m++;
        e[b].push_back(m); es[m]=E(a, 0); m++;
    }
    bool BFS() {
        memset(dis, -1, n * sizeof(int));
        ql = qr = 0;
        qq[qr++] = 0;
        dis[0] = 0;
        while ( ql != qr && dis[n-1] == -1 ) {
            int p = qq[ql++];
            for(auto& it : e[p]) {
                E ee = es[it];
                if ( ee.c == 0 || dis[ee.k] != -1 ) continue;
                dis[ee.k] = dis[p] + 1;
                qq[qr++] = ee.k;
            }
        }
        return dis[n-1] != -1;
    }
    long long go(int p, long long c) {
        if (p == n - 1) { return c; }
        long long ret = 0, tmp;
        for(int &i = ptr[p];i < SZ(e[p]); i++) {
            auto it = e[p][i];
            E &ee = es[it];
            if (ee.c == 0 || dis[p] + 1 != dis[ee.k]) { continue; }
            tmp = go(ee.k, min(c - ret, (long long)ee.c));
            ret += tmp; ee.c -= tmp; es[it ^ 1].c += tmp;
            if (ret == c) { break; }
        }
        if (ret == 0) { dis[p] = -1; }
        return ret;
    }
    long long maxflow() {
        long long ret = 0;
        while (BFS()) {
            memset(ptr,0,n * sizeof(int));
            ret += go(0, 1LL << 60);
        }
        return ret;
    }
} flow;
int get_type(PII x){
    if(x.S%2==0){
        if(x.F%2){return 0;}
        else {return 1;}
    }else{
        if(x.F%2==0){return 2;}
        else {return 3;}
    }
}
int n;
int x[SIZE],y[SIZE],w[SIZE];
int ty[SIZE];
map<PII,int>AA;
int dx[4]={1,0,-1,0};
int dy[4]={0,1,0,-1};
void solve() {
    flow.init(2*n+2);
    LL an=0;
    FOR(i,1,n){
        AA[MP(x[i],y[i])]=i;
        an+=w[i];
        flow.add_edge(i*2-1,i*2,w[i]);
        ty[i]=get_type(MP(x[i],y[i]));
        if(ty[i]==0){
            flow.add_edge(0,i*2-1,INF);
        }else if(ty[i]==3){
            flow.add_edge(i*2,2*n+1,INF);
        }
    }
    FOR(i,1,n){
        REP(j,4){
            int nx=x[i]+dx[j];
            int ny=y[i]+dy[j];
            auto it=AA.find(MP(nx,ny));
            if(it!=AA.end()){
                int nid=it->S;
                if(ty[nid]==ty[i]+1){
                    flow.add_edge(2*i,2*nid-1,INF);
                }
            }
        }
    }
    W(an-flow.maxflow());
}
void input() {
    R(n);
    FOR(i,1,n)R(x[i],y[i],w[i]);
}
int main(){
    input();
    solve();
    return 0;
}