#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <functional>
#include <string>
#include <cstdio>
#include <set>
using namespace std;

const int INF = 1<<28;

struct E {
  int to, cost, cap, rev;
  E(int to, int cost, int cap, int rev)
    : to(to), cost(cost), cap(cap), rev(rev) {}
  E() {}
};

typedef vector<vector<E> > G;

void addEdgeF(int from, int to, int cost, int cap, G &g) {
  g[from].push_back(E(to,cost,cap,g[to].size()));
  g[to].push_back(E(from,-cost,0,(int)g[from].size()-1));
}

int dfsF(int v, int t, int f, bool *used, G &g) {
  if(v == t) return f;
  used[v] = true;
  for(int i = 0; i < g[v].size(); ++i) {
    E &e = g[v][i];
    if(!used[e.to] && e.cap > 0) {
      int d = dfsF(e.to, t, min(f, e.cap), used, g);
      if(d > 0) {
        e.cap -= d;
        g[e.to][e.rev].cap += d;
        return d;
      }
    }
  }
  return 0;
}

int maxFlow(int s, int t, G g) {
  int flow = 0;
  bool *used = new bool[g.size()];
  while(1) {
    fill(used, used + g.size(), false);
    int f = dfsF(s, t, INF, used, g);
    if(f == 0) break;
    flow += f;
  }
  delete [] used;
  return flow;
}

typedef pair<int,int> Pair;

int minCostFlow(int s, int t, int f, G g) {
  int V = g.size();
  vector<int> h(V), dist(V), prevv(V), preve(V);
  int res = 0;
  fill(h.begin(), h.end(), 0);
  while(f > 0) {
    priority_queue<Pair, vector<Pair>, greater<Pair> > que;
    fill(dist.begin(), dist.end(), INF);
    dist[s] = 0;
    que.push(Pair(0, s));
    while(!que.empty()) {
      Pair p = que.top(); que.pop();
      int v = p.second;
      if(dist[v] < p.first) continue;
      for(int i = 0; i < g[v].size(); ++i) {
        E &e = g[v][i];
        int tmp = dist[v] + e.cost + h[v] - h[e.to];
        if(e.cap > 0 && dist[e.to] > tmp) {
          dist[e.to] = tmp;
          prevv[e.to] = v;
          preve[e.to] = i;
          que.push(Pair(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]) {
      E &e = g[prevv[v]][preve[v]];
      e.cap -= d;
      g[v][e.rev].cap += d;
    }
  }
  return res;
}

int getId(Pair p, map<Pair,int> &id) {
  if(!id.count(p)) id[p] = id.size();
  return id[p];
}

int main() {
  int n;
  while(cin >> n && n) {
    vector<vector<int> > x(n+2),y(n+2),c(n+2);
    int noc;
    G g((n+5)*50);
    map<Pair, int> id;
    for(int i = 0; i+1 < n; ++i) {
      int m;
      cin >> m;
      x[i] = vector<int>(m);
      y[i] = vector<int>(m);
      c[i] = vector<int>(m);
      for(int j = 0; j < m; ++j) {
        cin >> x[i][j] >> y[i][j] >> c[i][j];
      }
    }

    cin >> noc;

    //
    addEdgeF(getId(Pair(0*2,0),id), getId(Pair(0*2+1,0),id), 0, 1, g);
    for(int i = 0; i+1 < n; ++i) {
      set<int> s;
      for(int j = 0; j < y[i].size(); ++j) {
        if(s.count(y[i][j])) continue;
        s.insert(y[i][j]);
        addEdgeF(getId(Pair((i+1)*2,y[i][j]),id),
                 getId(Pair((i+1)*2+1,y[i][j]),id), 0, 1, g);
      }
    }
    addEdgeF(getId(Pair(n*2,0),id), getId(Pair(n*2+1,0),id), 0, 1, g);

    //
    for(int j = 0; j < x[0].size(); ++j) {
      addEdgeF(getId(Pair(0*2+1,0),id),
               getId(Pair(1*2,y[0][j]),id), c[0][j], 1, g);
    }
    for(int i = 0; i+2 < n; ++i) {
      for(int j = 0; j < x[i].size(); ++j) {
        for(int k = 0; k < x[i+1].size(); ++k) {
          if(y[i][j] <= x[i+1][k]) {
            addEdgeF(getId(Pair((i+1)*2+1,y[i][j]),id),
                     getId(Pair((i+2)*2,y[i+1][k]),id), c[i+1][k], 1, g);
          }
        }
      }
    }

    {
      set<int> s;
      for(int j = 0; j < y[n-2].size(); ++j) {
        if(s.count(y[n-2][j])) continue;
        s.insert(y[n-2][j]);
        addEdgeF(getId(Pair((n-1)*2+1,y[n-2][j]),id),
                 getId(Pair(n*2,0),id), 0, 1, g);
        
      }
    }

    int ans = 0;
    int cost = 0;
    for(int i = 1; i <= noc; ++i) {
      int tmp = minCostFlow(getId(Pair(1,0),id), getId(Pair(n*2,0),id), i, g);
      if(tmp == -1) break;
      else {
        ans = i;
        cost = tmp;
      }
    }

    for(int i = 0; i < g.size(); ++i) {
      for(int j = 0; j < g[i].size(); ++j) {
        E &e = g[i][j];
        //cout << i << ":" << e.to << ", " << e.cost << ", " << e.cap << ", " << e.rev << endl;
      }
    }
    cout << ans << " " << cost << endl;
  }
  return 0;
}

Measured memory_bytes: 5308