#include<iostream>
#include<vector>
#include<utility>
#include<algorithm>
#include<queue>
#include<functional>
#include<map>

using namespace std;

typedef pair<int,int> P;

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

const int N=99602;
const int INF=1<<29;
int V;
vector<vector<edge> > G;
int h[N];
int dist[N];
int prevv[N],preve[N];

void set_id(map<int,int> &m){
  int x=0;
  for(auto &e:m){
    e.second=x++;
  }
}

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

// pair<int,int> min_cost_flow(int s,int t,int g){
//   int res=0;
//   fill(h,h+V,0);
//   int f=0;
//   while(f<g){
//     priority_queue<P,vector<P>,greater<P> > que;
//     fill(dist,dist+V,INF);
//     dist[s]=0;
//     que.push({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({dist[e.to],e.to});
// 	}
//       }
//     }
//     if(dist[t]>=INF){
//       return {f,res};
//     }
//     for(int v=0;v<V;v++){
//       h[v]+=dist[v];
//     }
//     f++;
//     res+=h[t];
//     for(int v=t;v!=s;v=prevv[v]){
//       edge &e=G[prevv[v]][preve[v]];
//       e.cap--;
//       G[v][e.rev].cap++;
//     }
//   }
//   return {f,res};
// }

pair<int,int> min_cost_flow(int s,int t,int f){
  int res=0;
  const int INF=1<<29;
  fill(h,h+V,INF);
  h[s]=0;
  for(;;){
    bool u=false;
    for(int i=0;i<V;i++){
      for(auto f:G[i]){
	if(f.cap){
	  int nd=h[i]+f.cost;
	  if(nd<h[f.to]){
	    h[f.to]=nd;
	    u=true;
	  }
	}
      }
    }
    if(!u)break;
  }
  int g=0;
  while(g<f){
    priority_queue<P,vector<P>,greater<P> > que;
    fill(dist,dist+V,INF);
    dist[s]=0;
    que.push({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({dist[e.to],e.to});
	}
      }
    }
    if(dist[t]==INF)return {g,res};
    for(int v=0;v<V;v++){
      h[v]+=dist[v];
    }
    int d=INF;
    for(int v=t;v!=s;v=prevv[v]){
      d=min(d,G[prevv[v]][preve[v]].cap);
    }
    g+=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 {g,res};
}


int main(){
  for(int n;cin>>n,n;){
    map<int,int> in[100],out[100];
    int o[101]={2};
    int m[100];
    int x[100][20],y[100][20],c[100][20];
    G=vector<vector<edge> >(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];
	in[i][x[i][j]];
	out[i][y[i][j]];
      }
      set_id(in[i]);
      set_id(out[i]);
      for(int j=0;j<m[i];j++){
	add_edge(o[i]+in[i][x[i][j]],o[i]+in[i].size()+out[i][y[i][j]],c[i][j]);
      }
      if(i){
	for(auto e:out[i-1]){
	  for(auto f:in[i]){
	    if(e.first<=f.first){
	      add_edge(o[i-1]+in[i-1].size()+out[i-1].size()+e.second,o[i]+f.second);
	    }
	  }
	}
      }
      for(auto e:out[i]){
	add_edge(o[i]+in[i].size()+e.second,o[i]+in[i].size()+out[i].size()+e.second,0,1);
      }
      o[i+1]=o[i]+in[i].size()+2*out[i].size();
    }
    for(auto e:in[0]){
      add_edge(0,2+e.second);
    }
    for(auto f:out[n-2]){
      add_edge(o[n-2]+in[n-2].size()+out[n-2].size()+f.second,1);
    }
    V=o[n-1];
    int g;
    cin>>g;
    auto r=min_cost_flow(0,1,g);
    cout<<r.first<<' '<<r.second<<endl;
  }
}

    
 

Measured memory_bytes: 8308