#include <iostream>
#include <vector>
#include <queue>
#include <map>
#include <cstring>
using namespace std;

#define MAX_V 10000
#define INF 999999999
#define foreach(itr,c) for(__typeof(c.begin()) itr=c.begin();itr!=c.end();itr++)

typedef pair<int,int> P;

struct edge{
  int to, cap, cost, rev;
};

int V, S, T;
vector<edge> g[MAX_V], tg[MAX_V];
int h[MAX_V];
int dist[MAX_V];
int prevv[MAX_V], preve[MAX_V];

int N, M[102], G;
int X[102][22], Y[102][22], C[102][22];

void add_edge(int from, int to, int cap, int cost){
  tg[from].push_back((edge){to, cap, cost, tg[to].size()});
  tg[to].push_back((edge){from, 0, -cost, tg[from].size() - 1});
}

void show(){
  for(int i = 0; i < V; i++){
    cout << i << " : ";
    for(int j = 0; j < tg[i].size(); j++){
      cout << "[" << tg[i][j].to << ", " << tg[i][j].cap << ", " << tg[i][j].cost << "]";
    }
    cout<<endl;
  }
}

void make_graph(){
  for(int i = 0; i < MAX_V; i++){
    tg[i].clear();
  }

  map<int,int> node[N + 2];
  V = 1;
  S = 0;

  node[0][0] = 0;

  for(int i = 0; i < N - 1; i++){
    for(int j = 0; j < M[i]; j++){
      if(node[i + 1].find(Y[i][j]) == node[i + 1].end()){
        node[i + 1][Y[i][j]] = V;
        V++;
      }
    }
  }

  node[N][INF] = V;
  T = V;
  V++;

  foreach(i, node[N - 1]){
    add_edge(i->second, T, 1, 0);
  }

  for(int i = 0; i < N - 1; i++){
    foreach(j, node[i]){
      foreach(k, node[i + 1]){
        int minCost = INF;

        for(int l = 0; l < M[i]; l++){
          if(j->first <= X[i][l] && Y[i][l] == k->first){
            minCost = min(minCost, C[i][l]);
          }
        }

        if(minCost != INF){
          add_edge(j->second, k->second + V, 1, minCost);
        }
      }
    }
  }

  for(int i = 1; i < V - 1; i++){
    add_edge(i + V, i, 1, 0);
  }
  V *= 2;
}

void copy_graph(){
  for(int i = 0; i < V; i++){
    g[i] = tg[i];
  }
}

int min_cost_flow(int s, int t, int f){
  int res = 0;
  fill(h, h + V, 0);

  while(f > 0){
    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];
    }

    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;
}

int main(){
  while(cin >> N, N){
    for(int i = 0; i < N - 1; i++){
      cin >> M[i];
      for(int j = 0; j < M[i]; j++){
        cin >> X[i][j] >> Y[i][j] >> C[i][j];
      }
    }
    cin >> G;
    make_graph();

    int ans = -1;

    for(int i = G; i > 0; i--){
      copy_graph();

      ans = min_cost_flow(S, T, i);

      if(ans != -1){
        cout << i << " " << ans << endl;
        break;
      }
    }

    if(ans == -1){
      cout << "0 0" << endl;
    }
  }
}

Measured memory_bytes: 0