#include <iostream>
#include <iomanip>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <complex>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cassert>
#include <climits>
#include <queue>
#include <set>
#include <map>
#include <valarray>
#include <bitset>
#include <stack>
using namespace std;

#define REP(i,n) for(int i=0;i<(int)n;++i)
#define FOR(i,c) for(__typeof((c).begin())i=(c).begin();i!=(c).end();++i)
#define ALL(c) (c).begin(), (c).end()
typedef long long ll;
typedef pair<int,int> pii;
const int INF = 1<<29;
const double PI = acos(-1);
const double EPS = 1e-8;

typedef int Weight;
struct Edge {
  int src, dst;
  Weight capacity, cost;
  int rev;
  Edge(int src, int dst, Weight capacity, Weight cost) :
    src(src), dst(dst), capacity(capacity), cost(cost) { }
  Edge(int src, int dst, Weight capacity, Weight cost, int rev) :
    src(src), dst(dst), capacity(capacity), cost(cost), rev(rev) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.cost != f.cost ? e.cost > f.cost : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;

typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void add_edge2(Graph &g, int s, int d, Weight cap, Weight cost) {
  g[s].push_back(Edge(s,d,cap,cost,g[d].size()));
  g[d].push_back(Edge(d,s,0,-cost,g[s].size()-1));
}

pair<Weight, Weight> minimumCostFlow3(Graph g, int s, int t) {
  const int n = g.size();
  pair<Weight, Weight> total; // (cost, flow)

  for (int F = INF; F > 0;) { // residual flow
    vector<Weight> d(n, INF); d[s] = 0;
    vector<int> pv(n), pe(n);
    bool update = 1;
    while(update) {
      update = 0;
      REP(i, n) if (d[i] < INF) REP(j, g[i].size()) {
          Edge &e = g[i][j];
          if (e.capacity > 0 && d[e.dst] > d[i] + e.cost) {
            d[e.dst] = d[i] + e.cost;
            pv[e.dst] = i; pe[e.dst] = j;
            update = 1;
          }
        }
    }
    if (d[t] == INF) break;
    Weight f = F;
    for (int u = t; u != s; u = pv[u])
      f = min(f, g[pv[u]][pe[u]].capacity);
    if (!f) break;
    for (int u = t; u != s; u = pv[u]) {
      total.first += f * g[pv[u]][pe[u]].cost;
      g[pv[u]][pe[u]].capacity -= f;
      g[u][g[pv[u]][pe[u]].rev].capacity += f;
    }
    F -= f;
    total.second += f;
  }
  return total;
}

struct P {
  int x, y, c;
};
bool operator<(const P &a, const P &b) {
  return a.y < b.y;
}
int nodeid[100][20];
P p[100][20];
int sumnum[100];
int num[100];
int n;

int NODE1(int i, int j) { return sumnum[i]*2+j; }
int NODE2(int i, int j) { return sumnum[i]*2+num[i]+j; }
int SRC1() { return sumnum[n-1]*2; }
int SRC2()  { return sumnum[n-1]*2+1; } 
int SINK() { return sumnum[n-1]*2+2; }

int main() {
  while(cin >> n, n) {
    int m[n];
    REP(i, n-1) {
      cin >> m[i];
      REP(j, m[i]) cin >> p[i][j].x >> p[i][j].y >> p[i][j].c;
      sort(p[i], p[i]+m[i]);
      int pre = -1;
      num[i] = 0;
      REP(j, m[i]) {
        if (pre != p[i][j].y) {
          pre = p[i][j].y;
          num[i]++;
        }
        nodeid[i][j] = num[i]-1;
        //cout << p[i][j].x << " " << p[i][j].y << " -> " << nodeid[i][j] << endl;
      }
    }
    int classnum; cin >> classnum;
    memset(sumnum, 0, sizeof(sumnum));
    REP(i, n-1) sumnum[i+1] = sumnum[i] + num[i];
    // cout << "sumnum = ";
    // REP(i, n) cout << sumnum[i] << " ";cout<<endl;
    int N = sumnum[n-1]*2+3;
    Graph g(N);
    add_edge2(g, SRC1(), SRC2(), classnum, 0);
    REP(i, m[0]) {
      add_edge2(g, SRC2(), NODE1(0,nodeid[0][i]), 1, p[0][i].c);
    }
    REP(i, num[n-2]) {
      //cout << "node2 = " << sumnum[n-1] << " " << n-2 << " " << i << " " << NODE2(n-2,i) << endl;
      add_edge2(g, NODE2(n-2,i), SINK(), INF, 0);
    }
    REP(i, n-1) {
      REP(j, num[i]) {
        add_edge2(g, NODE1(i,j), NODE2(i,j), 1, 0);
      }
    }
    for (int i=1; i<n-1; ++i) {
      REP(j, m[i-1]) {
        REP(k, m[i]) {
          if (p[i-1][j].y > p[i][k].x) continue;
          add_edge2(g, NODE2(i-1,nodeid[i-1][j]), NODE1(i, nodeid[i][k]), 1, p[i][k].c);
        }
      }
    }
    // REP(i, N) {
    //   cout << "i = " << i << endl;
    //   FOR(it, g[i]) printf("%d(%d,%d) ",it->dst, it->capacity, it->cost);
    //   cout << endl;
    // }
    pii ans = minimumCostFlow3(g, SRC1(), SINK());
    cout << ans.second << " " << ans.first << endl;
  }
}

Measured memory_bytes: 0