#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cmath>
#include <cassert>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <numeric>
#include <complex>
#include <list>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <utility>
#include <functional>
#include <iterator>

using namespace std;

#define dump(n) cerr<<"# "<<#n<<"="<<(n)<<endl
#define repi(i,a,b) for(int i=int(a);i<int(b);i++)
#define peri(i,a,b) for(int i=int(b);i-->int(a);)
#define rep(i,n) repi(i,0,n)
#define per(i,n) peri(i,0,n)
#define iter(c) __typeof__((c).begin())
#define foreach(i,c) for(iter(c) i=(c).begin();i!=(c).end();++i)
#define all(c) (c).begin(),(c).end()
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int,int> pii;

const int INFTY=1<<29;

struct Train{
	int leave,arrive,fare;
	Train(){}
	Train(int l,int a,int f):leave(l),arrive(a),fare(f){}
};

struct Vertex{
	int kind; // 0:leave, 1:arrive
	int index,time;
	Vertex(){}
	Vertex(int k,int i,int t):kind(k),index(i),time(t){}
	bool operator<(const Vertex& v)const{
		if(kind!=v.kind) return kind<v.kind;
		if(index!=v.index) return index<v.index;
		if(time!=v.time) return time<v.time;
		return false;
	}
};

struct Edge{
	int src,dst,cap,cost;
	Edge(){}
	Edge(int s,int d,int ca,int co):src(s),dst(d),cap(ca),cost(co){}
};
typedef vector<vector<Edge> > Graph;

int MinCostFlow(const Graph& _g,int begin,int end,int flow)
{
	int size=_g.size();
	Graph g(size);
	vvi rev(size);
	rep(i,size) foreach(e,_g[i]){
		g[i].push_back(*e);
		g[e->dst].push_back(Edge(e->dst,e->src,0,-e->cost));
		rev[i].push_back(g[e->dst].size()-1);
		rev[e->dst].push_back(g[i].size()-1);
	}
	
	int res=0;
	vi pots(size);
	while(flow){
		vi dist(size,INFTY);
		vector<pii> prev(size,mp(-1,-1));
		priority_queue<pii,vector<pii>,greater<pii> > pq;
		pq.push(mp(0,begin));
		dist[begin]=0;
		while(!pq.empty()){
			int curd=pq.top().first,curv=pq.top().second; pq.pop();
			if(dist[curv]<curd)
				continue;
			rep(i,g[curv].size()){
				Edge e=g[curv][i];
				if(e.cap==0)
					continue;
				int newdist=dist[e.src]+e.cost+pots[e.src]-pots[e.dst];
				if(dist[e.dst]>newdist){
					dist[e.dst]=newdist;
					prev[e.dst]=mp(e.src,i);
					pq.push(mp(newdist,e.dst));
				}
			}
		}
		
		if(prev[end].first==-1)
			return -1;
		rep(i,size)
			pots[i]+=dist[i];
		
		int f=flow;
		for(int v=end;v!=begin;v=prev[v].first){
			Edge e=g[prev[v].first][prev[v].second];
			f=min(f,e.cap);
		}
		for(int v=end;v!=begin;v=prev[v].first){
			int i=prev[v].first,j=prev[v].second;
			g[i][j].cap-=f;
			g[g[i][j].dst][rev[i][j]].cap+=f;
		}
		flow-=f;
		res+=f*pots[end];
	}
	
	return res;
}

int main()
{
	for(int n;cin>>n,n;){
		vector<vector<Train> > train(n-1);
		rep(i,n-1){
			int m; cin>>m;
			train[i].resize(m);
			rep(j,m)
				cin>>train[i][j].leave>>train[i][j].arrive>>train[i][j].fare;
		}
		int c; cin>>c;
		
		map<Vertex,int> vmap;
		rep(i,n-1){
			rep(j,train[i].size()){
				vmap[Vertex(0,i,train[i][j].leave)];
				vmap[Vertex(1,i,train[i][j].arrive)];
			}
		}
		{
			int id=0;
			foreach(i,vmap)
				i->second=id++;
		}
		
		int lcnt=0,acnt=0;
		foreach(i,vmap){
			if(i->first.kind==0) lcnt++;
			if(i->first.kind==1) acnt++;
		}
		
		Graph g(lcnt+acnt+acnt+2);
		int source=lcnt+acnt+acnt,sink=source+1;
		
		rep(i,n-1){
			rep(j,train[i].size()){
				int src=vmap[Vertex(0,i,train[i][j].leave)];
				int dst=vmap[Vertex(1,i,train[i][j].arrive)];
				g[src].push_back(Edge(src,dst,1,train[i][j].fare));
			}
		}
		rep(i,n-1){
			rep(j,train[i].size()){
				int src=vmap[Vertex(1,i,train[i][j].arrive)];
				int dst=src+acnt;
				if(g[src].size()==0)
				g[src].push_back(Edge(src,dst,1,0));
			}
		}
		rep(i,n-1){
			if(i==n-2) continue;
			rep(j,train[i].size()){
				rep(k,train[i+1].size()){
					if(train[i][j].arrive<=train[i+1][k].leave){
						int src=vmap[Vertex(1,i,train[i][j].arrive)]+acnt;
						int dst=vmap[Vertex(0,i+1,train[i+1][k].leave)];
						g[src].push_back(Edge(src,dst,1,0));
					}
				}
			}
		}
		rep(i,train[0].size()){
			int dst=vmap[Vertex(0,0,train[0][i].leave)];
			g[source].push_back(Edge(source,dst,1,0));
		}
		rep(i,train[n-2].size()){
			int src=vmap[Vertex(1,n-2,train[n-2][i].arrive)]+acnt;
			g[src].push_back(Edge(src,sink,INFTY,0));
		}
		
		int lo=0,hi=c+1;
		while(lo+1<hi){
			int mi=(lo+hi)/2;
			if(MinCostFlow(g,source,sink,mi)==-1)
				hi=mi;
			else
				lo=mi;
		}
		
		int flow=lo;
		int cost=MinCostFlow(g,source,sink,flow);
		printf("%d %d\n",flow,cost);
	}
	
	return 0;
}

Measured memory_bytes: 4868