#include <bits/stdc++.h>

#define FOR(i,a,b) for(int i = (a);i < (b);i++)
#define RFOR(i,a,b) for(int i = (b)-1;i >= (a);i--)
#define REP(i,n) FOR(i,0,(n))
#define RREP(i,n) RFOR(i,0,(n))

using namespace std;

typedef pair<int, int> P;
#define pb push_back
#define mp make_pair
#define ft first
#define sd second

#define MAX_N 100
#define INF (1<<20)

int N;
int x[MAX_N], y[MAX_N], z[MAX_N], m[MAX_N];

bool input(){
  cin>>N;
  int a[3];
  REP(i, N) {
    cin>>a[0]>>a[1]>>a[2];
    sort(a, a+3);
    x[i] = a[0];
    y[i] = a[1];
    z[i] = a[2];
    m[i] = x[i]*y[i]*z[i];
  }
  return N!=0;
}

#define MAX_V 204
struct edge { int to, cap, cost, rev; };
int V; // ????????°
vector<edge> G[MAX_V]; // ??°???????????£??\???????????¨???
int h[MAX_V]; // ??????????????£???
int dist[MAX_V]; // ???????????¢
int prevv[MAX_V], preve[MAX_V]; // ??´??????????????¨???
// from??????to??????????????????cap????????????cost???????????°?????????????????????
void add_edge(int from, int to, int cap, int cost) {
    G[from].push_back((edge){to, cap, cost, (int)G[to].size()});
    G[to].push_back((edge){from, 0, -cost, (int)G[from].size() - 1});
}
// s??????t????????????f???????°??????¨???????±???????
// ??????????????´??????-1?????????
int min_cost_flow(int s, int t, int f) {
    int res = 0;
    fill(h, h + V, 0); // h????????????
    while (f > 0) {
        // ??????????????????????????¨??????h?????´??°??????
        priority_queue<P, vector<P>, greater<P> > que;
        fill(dist, dist + V, INF);
        dist[s] = 0;
        que.push(P(0, s));
        while (!que.empty()) {
            P p = que.top(); que.pop();
            int v = p.second;
            if (dist[v] < p.first) continue;
            for (int i = 0; i < G[v].size(); i++) {
                edge &e = G[v][i];
                if (e.cap > 0 && dist[e.to] > dist[v] + e.cost + h[v] - h[e.to]) {
                    dist[e.to] = dist[v] + e.cost + h[v] - h[e.to];
                    prevv[e.to] = v;
                    preve[e.to] = i;
                    que.push(P(dist[e.to], e.to));
                }
            }
        }
        if (dist[t] == INF) {
            // ????????\???????????????
            return -1;
        }
        for (int v = 0; v < V; v++) h[v] += dist[v];
        // s-t????????????????????£??????????????????
        int d = f;
        for (int v = t; v != s; v = prevv[v]) {
            d = min(d, G[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d * h[t];
        for (int v = t; v != s; v = prevv[v]) {
            edge &e = G[prevv[v]][preve[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}

void resetG(int ver){
  V = ver;
  REP(i,V)G[i].clear();//while(!G[i].empty()) G[i].pop_back();
}

void solve(){
 resetG(N * 2 + 2);
 REP(i,N){
   REP(j,N){
     if(i == j)
       continue;
     if(x[i] > x[j] && y[i] > y[j] && z[i] > z[j])
       add_edge(j,i + N, 1, 0);
   }
   add_edge(V-2, i, 1, 0);
   add_edge(i+N, V-1, 1, 0);
   add_edge(i, V-1, 1, m[i]);
 }
 cout<<min_cost_flow(V-2, V-1,N)<<endl;
}

int main(){
  cin.tie(0);

  while (input()){
    solve();
  }

  return 0;
}