#include <bits/stdc++.h>

using namespace std;

struct Data {
	int x, y, c;
};

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

vector< vector<Edge> > G;

void addEdge(int from, int to, int cap, int cost) {
//	cout << from << " " << to << " " << cap << " " << cost << endl;
	G[from].push_back({to, cap, cost, (int)G[to].size()});
	G[to].push_back({from, 0, -cost, (int)G[from].size()-1});
}

#define INF 1000000000

typedef pair<int, int> P;

int h[5000] = {0}, dist[5000], prevV[5000], prevE[5000];
int flow(int s, int t, int f) {
	int res = 0;
	while (f > 0) {
		fill(&dist[0], &dist[0]+5000, INF); dist[s] = 0;
/*
		priority_queue<P, vector<P>, greater<P> > Q; Q.push({0, s});
		while ( !Q.empty() ) {
			P p = Q.top(); Q.pop();
			int v = p.second;
			if (p.first > dist[v]) continue;

			for (int i = 0; i < G[v].size(); ++i) {
				Edge& e = G[v][i];
				if (e.cap > 0 && dist[v]+e.cost+h[v]-h[e.to] < dist[e.to]) {
					dist[e.to] = dist[v]+e.cost+h[v]-h[e.to];
					prevV[e.to] = v;
					prevE[e.to] = i;
					Q.push({dist[e.to], e.to});
				}
			}
			if (dist[v] < 0) {
				exit(1);
			}
		}
*/
		while (1) {
			bool isUpdated = false;
			for (int i = 0; i < G.size(); ++i) {
				if (dist[i] == INF) continue;
				for (int j = 0; j < G[i].size(); ++j) {
					Edge& e = G[i][j];
					if (e.cap > 0 && dist[i]+e.cost < dist[e.to]) {
						dist[e.to] = dist[i]+e.cost;
						prevV[e.to] = i;
						prevE[e.to] = j;
						isUpdated = true;
					}
				}
			}
			if (!isUpdated) break;
		}

		if (dist[t] == INF) {
			return -1;
		}

//		for (int i = 0; i < G.size(); ++i) h[i] = min(INF, h[i] + dist[i]);

		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 * dist[t];
//		res += d * h[t];
		for (int v = t; v != s; v = prevV[v]) {
			Edge& e = G[prevV[v]][prevE[v]];
			e.cap -= d;
			G[e.to][e.rev].cap += d;
		}
	}
	return res;
}

int main() {
	int N;
	while ( cin >> N, N ) {
		vector< vector<Data> > data(N-1);
		for (int i = 0; i < N-1; ++i) {
			int m; cin >> m;
			for (int j = 0; j < m; ++j) {
				int x, y, c; cin >> x >> y >> c;
				data[i].push_back({x, y, c});
			}
		}
		int g; cin >> g;

		vector< map<int, int> > conv(N-1);
		for (int i = 0; i < data.size(); ++i) {
			for (int j = 0; j < data[i].size(); ++j) {
				conv[i][data[i][j].y] = 40*i+2*j;
			}
		}

		int s = 40*(int)data.size(), t = s+1;
		G.clear(); G.resize(t+1);
		for (int i = 0; i < data[0].size(); ++i) {
			addEdge(s, conv[0][data[0][i].y], 1, data[0][i].c);
		}
		for (int i = 0; i < data.size()-1; ++i) {
			for (int j = 0; j < data[i].size(); ++j) {
				for (int k = 0; k < data[i+1].size(); ++k) {
					if (data[i][j].y <= data[i+1][k].x) {
						int y1 = data[i][j].y;
						int y2 = data[i+1][k].y;
						addEdge(conv[i][y1]+1, conv[i+1][y2], 1, data[i+1][k].c);
					}
				}
			}
		}
		for (int i = 0; i < N-1; ++i) {
			map<int, int>::iterator it = conv[i].begin();
			while (it != conv[i].end()) {
				int to = i == N-2 ? t : it->second+1;
				addEdge(it->second, to, 1, 0);
				++it;
			}
		}

		int ans = 0, ac = 0;
		int f = 0;
		for (int i = 1; i <= g; ++i) {
			int d = flow(s, t, 1);
			if (d > -1) {
				f += d;
				ans = i;
				ac = f;
			}
			else {
				break;
			}
		}
		cout << ans << " " << ac << endl;
//		cout << endl;
	}
}

Measured memory_bytes: 3516