Problem:
Problem G: Sports Days
会津大学附属小学校（会津大小）は日本有数の競技プログラマー養成校として有名である。
もちろん、運動会に参加しているときでさえアルゴリズムの修行を欠かせない。
競技プログラミング部部長のあなたはもちろんこの大会でも勝利したい。
今回はある競技に注目する。
ある競技とは会津大小で行われている伝統的な競技だ。
校庭にコーンがn個置いてある。
コーンは4色用意されている。
コーンのいくつかのペアは白線で描かれた矢印で結ばれている。
矢印は片側だけについており、整数が併記されている。
競技者はk人1チームとして行動する。
あるスタート地点のコーンからゴール地点のコーンまで矢印の上をその向きに移動する。
ただし、k人それぞれがゴール地点までの経路は異なる必要がある。
経路1と経路2が異なるというのは、
条件1　経路1と経路2で経由する矢印の本数が等しい場合、経路1でi番目に経由する矢印と経路2でi番目に経由する矢印が異なるようなiが存在すること。
条件2　経路1と経路2で経由する矢印の本数が異なっていること。
のいずれかを満たせば経路が異なっていると言える。
さらに、コーンの辿り方には禁止された色のパターンがあり、スタート地点からゴール地点までの経路でそのパターンを含んでしまった選手はリタイアとなる。
ただし、それ以外の経路はどのような経路を辿ってもよく、何度も同じコーン（スタート地点やゴール地点のコーンを含む）を通って良い。
また、矢印に併記された数字がスコアとして加算されていく。
この競技はより多くのチームメイトがより小さな合計スコアでゴール地点のコーンに辿りつけたチームが勝利となる。
部長のあなたはもちろんプログラミングでこの問題を解決できるはずだ。
ゴールまで移動可能な最大の人数を求めよ。
また、最大人数で辿り着いた時の最小スコアを求めよ。
ただし、いくらでもスコアを小さく出来る場合は -1 を出力せよ。
Input
入力は複数のテストケースから成り立っている。
テストケースの数は20ケースを超えない。
n
col
1
col
2
...
col
n
m
a
1
b
1
c
1
a
2
b
2
c
2
...
a
m
b
m
c
m
k
pattern
n( 2 ≤ n ≤ 100)はコーンの数を表す。
col
i
(1 ≤ col
i
≤ 4)はi番目のコーンの色を示す。
m(0 ≤ m ≤ 1,000) は矢印の数を表す。
a
i
は矢印の始点のコーンの番号, b
i
は終点のコーンの番号を表し、c
i
はその矢印のスコアを表す.
また、ひとつのコーンから伸びる矢印は10本までである。
(1 ≤ a
i
, b
i
≤ n, -1,000 ≤ c
i
≤ 1,000)
kは競技を行うチームの人数を示す。
(1 ≤ k ≤ 10)
pattern
は長さが10以下の1~4までの数字からなる文字列で、
移動が禁止されているパターンを示す。
スタート地点のコーンは1番目のコーンであり、
n番目のコーンがゴールである。
入力で与えられる数(n, col, m, a, b, c, k)はすべて整数である。
入力の終わりは0を含む1行で示される。
Output
出力は空白で区切られた二つの整数からなる。
1つ目は到達できる人数で、2つ目はその最小コストである。
もし、いくらでもスコアを小さく出来る場合は-1のみを含む１行を出力せよ。
一人も到達できない場合は0 0を出力せよ。
Sample Input
2
1
1
2
1 2 1
2 1 1
1
1111
2
1
1
2
1 2 1
2 1 1
1
11
2
1
1
2
1 2 1
2 1 1
10
1111
2
1
1
2
1 2 1
2 1 1
10
111111
2
1
1
2
1 2 -1
2 1 0
10
11
2
1
1
2
1 2 -1
2 1 0
10
1111
2
1
1
2
1 2 -1
2 1 0
10
12
2
1
1
2
1 2 -1
2 1 0
10
1111111111
0
Sample Output
1 1
0 0
1 1
2 4
0 0
1 -1
-1
4 -10

Submitted solutions:

code_snippet: // AOJ #1090
// Sports Days 2025.2.9

#include <bits/stdc++.h>
using namespace std;
using ll = long long; 
const ll INF = 1LL << 60;
 
vector<int> buildLPS(const string &pat) {
    int m = pat.size();
    vector<int> lps(m, 0);
    int len = 0;
    for (int i = 1; i < m; i++) {
        while(len > 0 && pat[i] != pat[len])
            len = lps[len-1];
        if(pat[i] == pat[len]) len++;
        lps[i] = len;
    }
    return lps;
}
 
vector<vector<int>> buildAutomaton(const string &pat) {
    int m = pat.size();
    vector<vector<int>> aut(m+1, vector<int>(5, 0));
    vector<int> lps = buildLPS(pat);
    for (int d = 1; d <= 4; d++){
        if (char('0' + d) == pat[0]) aut[0][d] = 1;
        else aut[0][d] = 0;
    }
    for (int s = 1; s <= m; s++){
        for (int d = 1; d <= 4; d++){
            if(s < m && char('0' + d) == pat[s])
                aut[s][d] = s + 1;
            else {
                if(s == 0) aut[s][d] = 0;
                else aut[s][d] = aut[lps[s-1]][d];
            }
        }
    }
    return aut;
}
 
struct Edge {
    int to;
    int cost;
    int rcost;
};

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    while(true){
        int n;
        cin >> n;
        if(n == 0) break;
 
        vector<int> color(n+1);
        for (int i = 1; i <= n; i++) cin >> color[i];
 
        int m;
        cin >> m;
        vector<vector<tuple<int,int,int>>> origEdges(n+1);
        for (int i = 0; i < m; i++){
            int a, b, c;
            cin >> a >> b >> c;
            origEdges[a].push_back({a, b, c});
        }
 
        int k;
        cin >> k;
 
        string pattern;
        cin >> pattern;
 
        int patLen = pattern.size();
        vector<vector<int>> aut = buildAutomaton(pattern);
 
        int V = n * patLen;
        vector<vector<Edge>> graph(V), revGraph(V);
 
        int initState = aut[0][ color[1] ];
        if(initState == patLen){
            cout << 0 << " " << 0 << endl;
            continue;
        }
        int startId = (1 - 1) * patLen + initState;
 
        for (int u = 1; u <= n; u++){
            for (int s = 0; s < patLen; s++){
                int nodeId = (u - 1) * patLen + s;
                for(auto &edgeInfo : origEdges[u]){
                    int a, v, cost;
                    tie(a, v, cost) = edgeInfo;
                    int ns = aut[s][ color[v] ];
                    if(ns == patLen) continue;
                    int vId = (v - 1) * patLen + ns;
                    Edge e; e.to = vId; e.cost = cost;
                    graph[nodeId].push_back(e);
 
                    Edge rev;
                    rev.to = nodeId; rev.cost = cost;
                    revGraph[vId].push_back(rev);
                }
            }
        }
 
        vector<bool> isGoal(V, false);
        for (int s = 0; s < patLen; s++){
            int goalId = (n - 1) * patLen + s;
            isGoal[goalId] = true;
        }
 
        vector<bool> reachable(V, false);
        {
            queue<int>q;
            q.push(startId);
            reachable[startId] = true;
            while(!q.empty()){
                int cur = q.front(); q.pop();
                for(auto &e : graph[cur]){
                    if(!reachable[e.to]){
                        reachable[e.to] = true;
                        q.push(e.to);
                    }
                }
            }
        }
 
        vector<bool> canReachGoal(V, false);
        {
            queue<int>q;
            for (int i = 0; i < V; i++){
                if(isGoal[i]){
                    canReachGoal[i] = true;
                    q.push(i);
                }
            }
            while(!q.empty()){
                int cur = q.front(); q.pop();
                for(auto &e : revGraph[cur]){
                    if(!canReachGoal[e.to]){
                        canReachGoal[e.to] = true;
                        q.push(e.to);
                    }
                }
            }
        }
 
        vector<bool> inValidSubgraph(V, false);
        for (int i = 0; i < V; i++){
            if(reachable[i] && canReachGoal[i])
                inValidSubgraph[i] = true;
        }
 
        vector<ll> potential(V, INF);
        potential[startId] = 0;
        bool negCycle = false;
 
        for (int iter = 0; iter < V; iter++){
            bool updated = false;
            for (int u = 0; u < V; u++){
                if(!inValidSubgraph[u]) continue;
                if(potential[u] == INF) continue;
                for(auto &e : graph[u]){
                    int v = e.to;
                    if(!inValidSubgraph[v]) continue;
                    if(potential[u] + e.cost < potential[v]){
                        potential[v] = potential[u] + e.cost;
                        updated = true;
                    }
                }
            }
            if(iter == V - 1 && updated) {
                negCycle = true;
                break;
            }
            if(!updated) break;
        }
 
        if(negCycle){
            cout << -1 << endl;
            continue;
        }
 
        for (int u = 0; u < V; u++){
            if(potential[u] == INF) continue;
            for(auto &e : graph[u]){
                if(potential[e.to] == INF) e.rcost = e.cost;
                else e.rcost = e.cost + (int)(potential[u] - potential[e.to]);
            }
        }
 
        vector<int> countPaths(V, 0);
        typedef pair<ll,int> pli;
        priority_queue<pli, vector<pli>, greater<pli>> pq;
        pq.push({0, startId});
 
        vector<ll> sol;
        while(!pq.empty() && (int)sol.size() < k){
            auto cur = pq.top();
            pq.pop();
            ll d = cur.first;
            int u = cur.second;
 
            countPaths[u]++;
            if(countPaths[u] > k) continue;
 
            if(isGoal[u]){
                ll origCost = d + potential[u] - potential[startId];
                sol.push_back(origCost);
                if((int)sol.size() == k) break;
            }
 
            for(auto &edge : graph[u]){
                int v = edge.to;
                ll nd = d + edge.rcost;
                pq.push({nd, v});
            }
        }
 
        if(sol.empty()){
            cout << 0 << " " << 0 << endl;
        } else {
            int numPaths = sol.size();
            ll total = 0;
            for(auto cost : sol) total += cost;
            cout << numPaths << " " << total << endl;
        }
    }
    return 0;
}
accuracy: 0.5384615384615384
time_ms: 10
memory_kb: 4116
final_rank: 12

code_snippet: #include<bits/stdc++.h>
#define rep(i,n) for(int i=0;i<(int)(n);i++)
using namespace std;
typedef vector<int> vi;
typedef pair<int,int> pii;
typedef vector< vector<pii> > graph;

const int INF = 1e9;

inline int match(int cur, int in, const string &s){
  string prv = s.substr(0,cur) + (char)(in+'0');
  rep(i,cur+1){
    int len = cur+1-i;
    if(s.substr(0,len) == prv.substr(i,len))return len;
  }
  return 0;
}

void dfs(int cur, vector<int> &vis, graph &g){
  if(vis[cur])return;
  vis[cur] = 1;
  for(pii e : g[cur])dfs(e.second, vis, g);
}

bool BellmanFord(int s, int V, vector<int> &d, const graph &g){
  d = vi(V,INF);
  d[s] = 0;
  rep(azu,V){
    bool f = false;
    rep(i,V)for(pii e : g[i]){
      if(d[i]<INF && d[e.second] > d[i] + e.first){
	d[e.second] = d[i] + e.first;
	f = true;
      }
    }
    if(!f)return true;
  }
  return false;
}

int main(){
  cin.tie(0); ios::sync_with_stdio(0);

  int n,m,k,l;
  string pattern;
  while(cin >> n, n){
    vi col(n);
    rep(i,n)cin >> col[i], col[i]--;
    cin >> m;
    graph base(n);
    rep(i,m){
      int a,b,c;
      cin >> a >> b >> c; a--; b--;
      base[a].push_back(pii(c,b));
    }    
    cin >> k >> pattern;
    l = pattern.size();

    vector<vi> trans(l, vi(4,0));
    rep(i,l)rep(j,4){
      trans[i][j] = match(i,j+1,pattern);
    }

    int V = n*l;
    graph g(V), rg(V);
    rep(i,l)rep(j,n){
      for(pii e : base[j]){
	int to = e.second, nxt = trans[i][col[to]];
	if(nxt == l)continue;
	g[i*n+j].push_back(pii(e.first, nxt*n+to));
	rg[nxt*n+to].push_back(pii(e.first, i*n+j));
      }
    }

    if(trans[0][col[0]] == l){
      cout << "0 0" << endl;
      continue;
    }

    int S = trans[0][col[0]]*n;
    vi vis(V,0), rvis(V,0);
    dfs(S,vis,g);
    rep(i,l)dfs(i*n+n-1,rvis,rg);

    rep(i,V){
      if(vis[i]==0 || rvis[i]==0)g[i].clear();
      rep(j,g[i].size()){
	int to = g[i][j].second;
	if(vis[to]==0 || rvis[to]==0){
	  g[i].erase(g[i].begin()+j);
	  j--;
	}
      }
    }
    

    vi h;
    if(!BellmanFord(S, V, h, g)){
      cout << -1 << endl;
      continue;
    }

    vector< vi > d(V, vi(k,INF));
    d[S][0] = 0;
    priority_queue< pii, vector<pii>, greater<pii> > q;
    q.push(pii(0,S));

    while(q.size()){
      pii p = q.top(); q.pop();
      int v = p.second, c = p.first;

      for(pii e : g[v]){
	int nv = e.second, nc = c + e.first + h[v] - h[nv];
	bool f = true;
	rep(i,k){
	  if(d[nv][i] > nc){
	    if(f)q.push(pii(nc,nv)), f=false;
	    swap(d[nv][i],nc);
	  }
	}
      }
    }
	    
    vi can;
    rep(i,l)rep(j,k){
      if(d[i*n+n-1][j]!=INF){
	can.push_back(d[i*n+n-1][j] - h[S] + h[i*n+n-1]);
      }
    }
    sort(can.begin(),can.end());

    int ans = min((int)can.size(),k);
    long long sum = 0;
    rep(i,ans)sum += can[i];
    cout << ans << " " << sum << endl;
  }
}
accuracy: 1
time_ms: 50
memory_kb: 1712
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define dump(...) cout<<"# "<<#__VA_ARGS__<<'='<<(__VA_ARGS__)<<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 all(c) begin(c),end(c)
#define mp make_pair
#define mt make_tuple

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

template<typename T1,typename T2>
ostream& operator<<(ostream& os,const pair<T1,T2>& p){
	return os<<'('<<p.first<<','<<p.second<<')';
}

template<typename Tuple>
void print_tuple(ostream&,const Tuple&){}
template<typename Car,typename... Cdr,typename Tuple>
void print_tuple(ostream& os,const Tuple& t){
	print_tuple<Cdr...>(os,t);
	os<<(sizeof...(Cdr)?",":"")<<get<sizeof...(Cdr)>(t);
}
template<typename... Args>
ostream& operator<<(ostream& os,const tuple<Args...>& t){
	print_tuple<Args...>(os<<'(',t);
	return os<<')';
}

template<typename Ch,typename Tr,typename C>
basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>& os,const C& c){
	os<<'[';
	for(auto i=begin(c);i!=end(c);++i)
		os<<(i==begin(c)?"":" ")<<*i;
	return os<<']';
}

constexpr int INF=1e9;
constexpr int MOD=1e9+7;
constexpr double EPS=1e-9;

struct Edge{
	int src,dst,weight;
	Edge(){}
	Edge(int s,int d,int w):src(s),dst(d),weight(w){}
};
typedef vector<vector<Edge>> Graph;
bool operator<(const Edge& a,const Edge& b){return a.weight<b.weight;}
bool operator>(const Edge& a,const Edge& b){return a.weight>b.weight;}

// (頂点,その頂点を含めて禁止パターンにマッチした文字数)でグラフを拡張
Graph extend(const Graph& g,const vi& colors,const vi& forbidden)
{
	vi fail(forbidden.size()+1);
	fail[0]=-1;
	for(int i=0,j=-1;i<forbidden.size();){
		while(j>=0 && forbidden[i]!=forbidden[j])
			j=fail[j];
		i++,j++;
		fail[i]=j;
	}
	
	Graph g2;
	map<pii,int> f;
	queue<tuple<int,int,int,int,int>> q; q.emplace(-1,-1,0,0,0);
	while(q.size()){
		int u,i,v,j,w; tie(u,i,v,j,w)=q.front(); q.pop();
		while(j>=0 && colors[v]!=forbidden[j])
			j=fail[j];
		j++;
		if(j==forbidden.size()) continue;
		if(f.insert(mp(mp(v,j),f.size())).second){
			g2.resize(g2.size()+1);
			for(auto e:g[v]) q.emplace(v,j,e.dst,j,e.weight);
		}
		if(u>=0)
			g2[f[mp(u,i)]].emplace_back(f[mp(u,i)],f[mp(v,j)],w);
	}
	
	// 拡張したグラフには，始点が0~1個，終点が0~n個あるので
	// それぞれ1つずつとなるようにまとめる
	int src=g2.size(),dst=g2.size()+1;
	g2.resize(g2.size()+2);
	for(auto p:f){
		int i=p.first.first,v=p.second;
		if(i==0){
			g2[src].emplace_back(src,v,0);
			break;
		}
	}
	for(auto p:f){
		int i=p.first.first,v=p.second;
		if(i==colors.size()-1)
			g2[v].emplace_back(v,dst,0);
	}
	return g2;
}

// V'={v: src ~> v AND v ~> dst}の誘導部分グラフを構築
Graph induce(const Graph& g)
{
	int n=g.size(),src=n-2,dst=n-1;
	
	vi vis(n);
	{
		queue<int> q; q.push(src);
		while(q.size()){
			int u=q.front(); q.pop();
			if(vis[u]) continue;
			vis[u]=1;
			for(auto e:g[u]) q.push(e.dst);
		}
	}
	{
		Graph ig(n);
		rep(i,n) for(auto e:g[i])
			ig[e.dst].emplace_back(e.dst,e.src,e.weight);
		vi vis2(n);
		queue<int> q; q.push(dst);
		while(q.size()){
			int u=q.front(); q.pop();
			if(vis2[u]) continue;
			vis2[u]=1;
			for(auto e:ig[u]) q.push(e.dst);
		}
		rep(i,n) vis[i]&=vis2[i];
	}
	
	Graph g2(n);
	rep(i,n) for(auto e:g[i])
		if(vis[e.src] && vis[e.dst])
			g2[e.src].emplace_back(e.src,e.dst,e.weight);
	return g2;
}

void solve(const Graph& g,int k)
{
	int n=g.size(),src=n-2,dst=n-1;
	
	// ポテンシャルを計算
	vi pots(n,INF); pots[src]=0;
	rep(i,n){
		bool updated=false;
		rep(j,n) for(auto e:g[j])
			if(pots[e.dst]>pots[e.src]+e.weight){
				pots[e.dst]=pots[e.src]+e.weight;
				updated=true;
			}
		if(i==n-1 && updated){
			cout<<-1<<endl;
			return;
		}
	}
	
	vvi dist(n);
	priority_queue<Edge,vector<Edge>,greater<Edge>> pq; pq.emplace(-1,0,0);
	while(pq.size()){
		Edge cur=pq.top(); pq.pop();
		if(dist[cur.dst].size()==k) continue;
		dist[cur.dst].push_back(cur.weight);
		for(auto e:g[cur.dst])
			pq.emplace(e.src,e.dst,cur.weight+e.weight+pots[e.src]-pots[e.dst]);
	}
	
	int res=0;
	for(int x:dist[dst]) res+=x+pots[dst];
	cout<<dist[dst].size()<<' '<<res<<endl;
}

int main()
{
	for(int n;cin>>n && n;){
		vi colors(n);
		rep(i,n) cin>>colors[i];
		int m; cin>>m;
		Graph g(n);
		rep(i,m){
			int u,v,w; cin>>u>>v>>w; u--,v--;
			g[u].emplace_back(u,v,w);
		}
		int k; cin>>k;
		vi forbidden;
		{
			string s; cin>>s;
			for(char c:s) forbidden.push_back(c-'0');
		}
		
		g=induce(extend(g,colors,forbidden));
		solve(g,k);
	}
}
accuracy: 1
time_ms: 190
memory_kb: 2136
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

#define dump(...) cout<<"# "<<#__VA_ARGS__<<'='<<(__VA_ARGS__)<<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 all(c) begin(c),end(c)
#define mp make_pair
#define mt make_tuple

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

template<typename T1,typename T2>
ostream& operator<<(ostream& os,const pair<T1,T2>& p){
	return os<<'('<<p.first<<','<<p.second<<')';
}

template<typename Tuple>
void print_tuple(ostream&,const Tuple&){}
template<typename Car,typename... Cdr,typename Tuple>
void print_tuple(ostream& os,const Tuple& t){
	print_tuple<Cdr...>(os,t);
	os<<(sizeof...(Cdr)?",":"")<<get<sizeof...(Cdr)>(t);
}
template<typename... Args>
ostream& operator<<(ostream& os,const tuple<Args...>& t){
	print_tuple<Args...>(os<<'(',t);
	return os<<')';
}

template<typename Ch,typename Tr,typename C>
basic_ostream<Ch,Tr>& operator<<(basic_ostream<Ch,Tr>& os,const C& c){
	os<<'[';
	for(auto i=begin(c);i!=end(c);++i)
		os<<(i==begin(c)?"":" ")<<*i;
	return os<<']';
}

constexpr int INF=1e9;
constexpr int MOD=1e9+7;
constexpr double EPS=1e-9;

struct Edge{
	int src,dst,weight;
	Edge(){}
	Edge(int s,int d,int w):src(s),dst(d),weight(w){}
};
typedef vector<vector<Edge>> Graph;
bool operator<(const Edge& a,const Edge& b){return a.weight<b.weight;}
bool operator>(const Edge& a,const Edge& b){return a.weight>b.weight;}

ostream& operator<<(ostream& os,const Edge& e){
	return os<<'('<<e.src<<','<<e.dst<<':'<<e.weight<<')';
}
void print(const Graph& g)
{
	rep(i,g.size()){
		cout<<i<<':';
		for(auto e:g[i]) cout<<" ("<<e.dst<<':'<<e.weight<<')';
		cout<<endl;
	}
}


// (頂点,その頂点を含めて禁止パターンにマッチした文字数)でグラフを拡張
Graph extend(const Graph& g,const vi& colors,const vi& forbidden)
{
	vi fail(forbidden.size()+1);
	fail[0]=-1;
	for(int i=0,j=-1;i<forbidden.size();){
		while(j>=0 && forbidden[i]!=forbidden[j])
			j=fail[j];
		i++,j++;
		fail[i]=j;
	}
	
	Graph g2;
	map<pii,int> f;
	queue<tuple<int,int,int,int,int>> q; q.emplace(-1,-1,0,0,0);
	while(q.size()){
		int u,i,v,j,w; tie(u,i,v,j,w)=q.front(); q.pop();
		while(j>=0 && colors[v]!=forbidden[j])
			j=fail[j];
		j++;
		if(j==forbidden.size()) continue;
		bool newv=f.insert(mp(mp(v,j),f.size())).second;
		if(newv) g2.resize(g2.size()+1);
		if(u>=0) g2[f[mp(u,i)]].emplace_back(f[mp(u,i)],f[mp(v,j)],w);
		if(newv)
			for(auto e:g[v])
				q.emplace(v,j,e.dst,j,e.weight);
	}
	
	// 拡張したグラフには，始点が0~1個，終点が0~n個あるので
	// それぞれ1つずつとなるようにまとめる
	int src=g2.size(),dst=g2.size()+1;
	g2.resize(g2.size()+2);
	for(auto p:f){
		int i=p.first.first,v=p.second;
		if(i==0){
			g2[src].emplace_back(src,v,0);
			break;
		}
	}
	for(auto p:f){
		int i=p.first.first,v=p.second;
		if(i==colors.size()-1)
			g2[v].emplace_back(v,dst,0);
	}
	return g2;
}

// V'={v: src ~> v AND v ~> dst}の誘導部分グラフを構築
Graph induce(const Graph& g)
{
	int src=g.size()-2,dst=g.size()-1;
	
	vi vis1(g.size());
	queue<int> q; q.push(src);
	while(q.size()){
		int u=q.front(); q.pop();
		if(vis1[u]) continue;
		vis1[u]=1;
		for(auto e:g[u]) q.push(e.dst);
	}
	
	Graph ig(g.size());
	rep(i,g.size()) for(auto e:g[i])
		ig[e.dst].emplace_back(e.dst,e.src,e.weight);
	
	vi vis2(g.size());
	q.push(dst);
	while(q.size()){
		int u=q.front(); q.pop();
		if(vis2[u]) continue;
		vis2[u]=1;
		for(auto e:ig[u]) q.push(e.dst);
	}
	
	Graph g2(g.size());
	rep(i,g.size()) for(auto e:g[i])
		if(vis1[e.src] && vis2[e.src] && vis1[e.dst] && vis2[e.dst])
			g2[e.src].emplace_back(e.src,e.dst,e.weight);
	return g2;
}

void solve(const Graph& g,int k)
{
	int n=g.size();
	int src=g.size()-2,dst=g.size()-1;
	
	vi pots(n,INF); pots[src]=0;
	rep(i,n){
		bool updated=false;
		rep(j,n) for(auto e:g[j])
			if(pots[e.dst]>pots[e.src]+e.weight){
				pots[e.dst]=pots[e.src]+e.weight;
				updated=true;
			}
		if(i==n-1 && updated){
			cout<<-1<<endl;
			return;
		}
	}
	
	vvi dist(n);
	priority_queue<Edge,vector<Edge>,greater<Edge>> pq; pq.emplace(-1,0,0);
	while(pq.size()){
		Edge cur=pq.top(); pq.pop();
		if(dist[cur.dst].size()==k) continue;
		dist[cur.dst].push_back(cur.weight);
		for(auto e:g[cur.dst])
			pq.emplace(e.src,e.dst,cur.weight+e.weight+pots[e.src]-pots[e.dst]);
	}
	//dump(g);
	//dump(pots);
	//dump(dist);
	//rep(i,n){
	//	rep(j,dist[i].size()) cout<<dist[i][j]+pots[i]<<' ';
	//	cout<<endl;
	//}
	
	int res=0;
	for(int x:dist[dst]) res+=x+pots[dst];
	cout<<dist[dst].size()<<' '<<res<<endl;
}

int main()
{
	for(int n;cin>>n && n;){
		vi colors(n);
		rep(i,n) cin>>colors[i];
		int m; cin>>m;
		Graph g(n);
		rep(i,m){
			int u,v,w; cin>>u>>v>>w; u--,v--;
			g[u].emplace_back(u,v,w);
		}
		int k; cin>>k;
		vi forbidden;
		{
			string s; cin>>s;
			rep(i,s.size()) forbidden.push_back(s[i]-'0');
		}
		
		g=induce(extend(g,colors,forbidden));
		solve(g,k);
	}
}
accuracy: 1
time_ms: 200
memory_kb: 2204
final_rank: 4

code_snippet: //#define _GLIBCXX_DEBUG
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <algorithm>
#include <cassert>

using namespace std;

#define FOREACH(it,c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); ++it)
#define TIMES(i,n) for(int i = 0; i < (n); ++i)

typedef long long Cost;
const long long INF = 1000*1000*10*10*2*10LL;

struct Edge {
    int from, to;
    Cost cost;

    Edge() {}
    Edge(int f, int t, Cost c) : from(f), to(t), cost(c) {}
};

struct DistTag {
    int size;
    deque<Cost> buf, newbie;

    DistTag(int size) : size(size), buf(size, INF) {
        //newbie.reserve(size);
    }

    bool insert(Cost val) {
        if(buf.back() <= val) return false;
        deque<Cost>::iterator ins_pos = upper_bound(newbie.begin(), newbie.end(), val);
        newbie.insert(ins_pos, val);
        if(static_cast<int>(newbie.size()) > size) newbie.pop_back();
        return true;
    }

    bool has(Cost val) {
        return buf.back() >= val;
    }

    void flush() {
        FOREACH(it, newbie) {
            deque<Cost>::iterator ins_pos = upper_bound(buf.begin(), buf.end(), *it);
            buf.insert(ins_pos, *it);
        }
        buf.resize(size);
        newbie.clear();
    }
};

struct State {
    int pos;
    Cost cost;

    State() {}
    State(int p, Cost c) : pos(p), cost(c) {}

    bool operator <(const State &other) const {
        return cost > other.cost; // Reversed
    }
};

typedef vector<Edge> EdgeList;

void check_reachable(int start, const vector<EdgeList> &graph, vector<unsigned char> &reachable) {
    queue<int> q;
    q.push(start);
    reachable[start] = 1;
    while(!q.empty()) {
        int cur = q.front();
        q.pop();
        FOREACH(it, graph[cur]) {
            if(!reachable[it->to]) {
                reachable[it->to] = 1;
                q.push(it->to);
            }
        }
    }
}

bool relax(const vector<EdgeList> &graph, vector<Cost> &dist) {
    bool updated = false;
    FOREACH(list_it, graph) {
        FOREACH(it, *list_it) {
            const Cost cost = dist[it->from] + it->cost;
            if(dist[it->to] > cost) {
                dist[it->to] = cost;
                updated = true;
            }
        }
    }
    return updated;
}

pair<int,Cost> search(int start, const vector<EdgeList> &graph, int N, int P, int K) {
    vector<DistTag> dist(graph.size(), DistTag(K));
    dist[start].insert(0);

    TIMES(_, static_cast<int>(graph.size())*K) {
        TIMES(i, static_cast<int>(graph.size())) {
            DistTag &dt = dist[i];
            if(dt.newbie.size() == 0) continue;
            vector<int> tmp;
            FOREACH(it, graph[i]) {
                assert(it->from == i);
                // Corner case: loop edge
                if(it->to == i) {
                    FOREACH(nit, dt.newbie) {
                        tmp.push_back(*nit + it->cost);
                    }
                } else {
                    FOREACH(nit, dt.newbie) {
                        //cout << "insert " << i << ' ' << it->to << endl;
                        dist[it->to].insert(*nit + it->cost);
                    }
                }
            }
            dt.flush();
            FOREACH(tit, tmp) {
                dt.insert(*tit);
            }
        }
    }
    pair<int,Cost> res(0, 0);
    vector<Cost> costs;
    TIMES(i, P) {
        FOREACH(it, dist[(N-1)*P+i].buf) {
            costs.push_back(*it);
        }
    }
    sort(costs.begin(), costs.end());
    TIMES(i, min(K, static_cast<int>(costs.size()))) {
        if(costs[i] == INF) break;
        res.first++;
        res.second += costs[i];
    }
    return res;
}

pair<int,Cost> solve(int N) {
    vector<int> color_of(N);
    TIMES(i, N) {
        cin >> color_of[i];
        --color_of[i];
    }
    int M;
    cin >> M;
    vector<Edge> edges(M);
    TIMES(i, M) {
        Edge &e = edges[i];
        cin >> e.from >> e.to >> e.cost;
        --e.from; --e.to;
    }
    int K;
    cin >> K;
    vector<int> prohibited;
    {
        string str;
        cin >> str;
        FOREACH(it, str) {
            prohibited.push_back(*it - '0' - 1);
        }
    }
    const int P = prohibited.size();
    vector<vector<int> > next_prohibited_pos(P, vector<int>(4, 0));
    {
        int shadow = 0;
        TIMES(i, P) {
            next_prohibited_pos[i][prohibited[i]] = i+1;
            if(i > 0) {
                TIMES(j, 4) {
                    if(j != prohibited[i]) next_prohibited_pos[i][j] = next_prohibited_pos[shadow][j];
                }
                shadow = next_prohibited_pos[shadow][prohibited[i]];
            }
        }
    }

    const int start = 0+next_prohibited_pos[0][color_of[0]];
    vector<EdgeList> graph(N*P);
    FOREACH(it, edges) {
        TIMES(i, P) {
            // Cannot reach this state.
            if(i > 0 && prohibited[i-1] != color_of[it->from]) continue;

            int np = next_prohibited_pos[i][color_of[it->to]];
            if(np < P) {
                graph[it->from*P+i].push_back(Edge(it->from*P+i, it->to*P+np, it->cost));
                //cout << it->from << ' ' << i << ' ' << it->to << ' ' << np << endl;
            }
        }
    }

    // Remove all unreachable nodes.
    // It causes fake negative loop detection.
    vector<unsigned char> reachable(N*P, 0);
    check_reachable(start, graph, reachable);
    TIMES(i, N*P) {
        if(!reachable[i]) graph[i].clear();
    }

    // Check if it has negative loop
    vector<Cost> dist(N*P, INF);
    dist[start] = 0;
    TIMES(_, N*P) {
        relax(graph, dist);
    }
    vector<Cost> tmp_last(P);
    TIMES(i, P) {
        tmp_last[i] = dist[(N-1)*P+i];
    }
    TIMES(_, N*P) {
        relax(graph, dist);
        TIMES(i, P) {
            if(dist[(N-1)*P+i] != tmp_last[i]) return make_pair(-1, -1);
        }
    }

    // Corner case: cannot start
    if(P == 1 && prohibited[0] == color_of[0]) return make_pair(0, 0);

    pair<int,Cost> res = search(start, graph, N, P, K);
    return res;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);

    int N;
    while(cin >> N) {
        if(!N) break;
        pair<int,Cost> ans = solve(N);
        if(ans.first == -1) cout << -1 << endl;
        else cout << ans.first << ' ' << ans.second << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 1500
memory_kb: 3108
final_rank: 10

code_snippet: #define _GLIBCXX_DEBUG
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <algorithm>
#include <cassert>

using namespace std;

#define FOREACH(it,c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); ++it)
#define TIMES(i,n) for(int i = 0; i < (n); ++i)

typedef long long Cost;
const long long INF = 1000*1000*10*10*2*10LL;

struct Edge {
    int from, to;
    Cost cost;

    Edge() {}
    Edge(int f, int t, Cost c) : from(f), to(t), cost(c) {}
};

struct DistTag {
    int size;
    deque<Cost> buf, newbie;

    DistTag(int size) : size(size), buf(size, INF) {
        //newbie.reserve(size);
    }

    bool insert(Cost val) {
        if(buf.back() <= val) return false;
        deque<Cost>::iterator ins_pos = upper_bound(newbie.begin(), newbie.end(), val);
        newbie.insert(ins_pos, val);
        if(static_cast<int>(newbie.size()) > size) newbie.pop_back();
        return true;
    }

    bool has(Cost val) {
        return buf.back() >= val;
    }

    void flush() {
        FOREACH(it, newbie) {
            deque<Cost>::iterator ins_pos = upper_bound(buf.begin(), buf.end(), *it);
            buf.insert(ins_pos, *it);
        }
        buf.resize(size);
        newbie.clear();
    }
};

struct State {
    int pos;
    Cost cost;

    State() {}
    State(int p, Cost c) : pos(p), cost(c) {}

    bool operator <(const State &other) const {
        return cost > other.cost; // Reversed
    }
};

typedef vector<Edge> EdgeList;

void check_reachable(int start, const vector<EdgeList> &graph, vector<unsigned char> &reachable) {
    queue<int> q;
    q.push(start);
    reachable[start] = 1;
    while(!q.empty()) {
        int cur = q.front();
        q.pop();
        FOREACH(it, graph[cur]) {
            if(!reachable[it->to]) {
                reachable[it->to] = 1;
                q.push(it->to);
            }
        }
    }
}

bool relax(const vector<EdgeList> &graph, vector<Cost> &dist) {
    bool updated = false;
    FOREACH(list_it, graph) {
        FOREACH(it, *list_it) {
            const Cost cost = dist[it->from] + it->cost;
            if(dist[it->to] > cost) {
                dist[it->to] = cost;
                updated = true;
            }
        }
    }
    return updated;
}

pair<int,Cost> search(int start, const vector<EdgeList> &graph, int N, int P, int K) {
    vector<DistTag> dist(graph.size(), DistTag(K));
    dist[start].insert(0);

    TIMES(_, static_cast<int>(graph.size())*K) {
        TIMES(i, static_cast<int>(graph.size())) {
            DistTag &dt = dist[i];
            if(dt.newbie.size() == 0) continue;
            FOREACH(it, graph[i]) {
                assert(it->from == i);
                FOREACH(nit, dt.newbie) {
                    //cout << "insert " << i << ' ' << it->to << endl;
                    dist[it->to].insert(*nit + it->cost);
                }
            }
            dt.flush();
        }
    }
    pair<int,Cost> res(0, 0);
    vector<Cost> costs;
    TIMES(i, P) {
        FOREACH(it, dist[(N-1)*P+i].buf) {
            costs.push_back(*it);
        }
    }
    sort(costs.begin(), costs.end());
    TIMES(i, min(K, static_cast<int>(costs.size()))) {
        if(costs[i] == INF) break;
        res.first++;
        res.second += costs[i];
    }
    return res;
}

pair<int,Cost> solve(int N) {
    vector<int> color_of(N);
    TIMES(i, N) {
        cin >> color_of[i];
        --color_of[i];
    }
    int M;
    cin >> M;
    vector<Edge> edges(M);
    TIMES(i, M) {
        Edge &e = edges[i];
        cin >> e.from >> e.to >> e.cost;
        --e.from; --e.to;
    }
    int K;
    cin >> K;
    vector<int> prohibited;
    {
        string str;
        cin >> str;
        FOREACH(it, str) {
            prohibited.push_back(*it - '0' - 1);
        }
    }
    const int P = prohibited.size();
    vector<vector<int> > next_prohibited_pos(P, vector<int>(4, 0));
    {
        int shadow = 0;
        TIMES(i, P) {
            next_prohibited_pos[i][prohibited[i]] = i+1;
            if(i > 0) {
                TIMES(j, 4) {
                    if(j != prohibited[i]) next_prohibited_pos[i][j] = next_prohibited_pos[shadow][j];
                }
                shadow = next_prohibited_pos[shadow][prohibited[i]];
            }
        }
    }

    const int start = 0+next_prohibited_pos[0][color_of[0]];
    vector<EdgeList> graph(N*P);
    FOREACH(it, edges) {
        TIMES(i, P) {
            // Cannot reach this state.
            if(i > 0 && prohibited[i-1] != color_of[it->from]) continue;

            int np = next_prohibited_pos[i][color_of[it->to]];
            if(np < P) {
                graph[it->from*P+i].push_back(Edge(it->from*P+i, it->to*P+np, it->cost));
                //cout << it->from << ' ' << i << ' ' << it->to << ' ' << np << endl;
            }
        }
    }

    // Remove all unreachable nodes.
    // It causes fake negative loop detection.
    vector<unsigned char> reachable(N*P, 0);
    check_reachable(start, graph, reachable);
    TIMES(i, N*P) {
        if(!reachable[i]) graph[i].clear();
    }

    // Check if it has negative loop
    vector<Cost> dist(N*P, INF);
    dist[start] = 0;
    TIMES(_, N*P) {
        relax(graph, dist);
    }
    vector<Cost> tmp_last(P);
    TIMES(i, P) {
        tmp_last[i] = dist[(N-1)*P+i];
    }
    TIMES(_, N*P) {
        relax(graph, dist);
        TIMES(i, P) {
            if(dist[(N-1)*P+i] != tmp_last[i]) return make_pair(-1, -1);
        }
    }

    // Corner case: cannot start
    if(P == 1 && prohibited[0] == color_of[0]) return make_pair(0, 0);

    pair<int,Cost> res = search(start, graph, N, P, K);
    return res;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);

    int N;
    while(cin >> N) {
        if(!N) break;
        pair<int,Cost> ans = solve(N);
        if(ans.first == -1) cout << -1 << endl;
        else cout << ans.first << ' ' << ans.second << endl;
    }
    return 0;
}
accuracy: 0.5384615384615384
time_ms: 20
memory_kb: 1452
final_rank: 11

code_snippet: #define _GLIBCXX_DEBUG
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <deque>
#include <algorithm>
#include <cassert>

using namespace std;

#define FOREACH(it,c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); ++it)
#define TIMES(i,n) for(int i = 0; i < (n); ++i)

typedef long long Cost;
const long long INF = 1000*1000*10*10*2*10LL;

struct Edge {
    int from, to;
    Cost cost;

    Edge() {}
    Edge(int f, int t, Cost c) : from(f), to(t), cost(c) {}
};

struct DistTag {
    int size;
    deque<Cost> buf, newbie;

    DistTag(int size) : size(size), buf(size, INF) {
        //newbie.reserve(size);
    }

    bool insert(Cost val) {
        if(buf.back() <= val) return false;
        deque<Cost>::iterator ins_pos = upper_bound(newbie.begin(), newbie.end(), val);
        newbie.insert(ins_pos, val);
        if(static_cast<int>(newbie.size()) > size) newbie.pop_back();
        return true;
    }

    bool has(Cost val) {
        return buf.back() >= val;
    }

    void flush() {
        FOREACH(it, newbie) {
            deque<Cost>::iterator ins_pos = upper_bound(buf.begin(), buf.end(), *it);
            buf.insert(ins_pos, *it);
        }
        buf.resize(size);
        newbie.clear();
    }
};

struct State {
    int pos;
    Cost cost;

    State() {}
    State(int p, Cost c) : pos(p), cost(c) {}

    bool operator <(const State &other) const {
        return cost > other.cost; // Reversed
    }
};

typedef vector<Edge> EdgeList;

void check_reachable(int start, const vector<EdgeList> &graph, vector<unsigned char> &reachable) {
    queue<int> q;
    q.push(start);
    reachable[start] = 1;
    while(!q.empty()) {
        int cur = q.front();
        q.pop();
        FOREACH(it, graph[cur]) {
            if(!reachable[it->to]) {
                reachable[it->to] = 1;
                q.push(it->to);
            }
        }
    }
}

bool relax(const vector<EdgeList> &graph, vector<Cost> &dist) {
    bool updated = false;
    FOREACH(list_it, graph) {
        FOREACH(it, *list_it) {
            const Cost cost = dist[it->from] + it->cost;
            if(dist[it->to] > cost) {
                dist[it->to] = cost;
                updated = true;
            }
        }
    }
    return updated;
}

pair<int,Cost> search(int start, const vector<EdgeList> &graph, int N, int P, int K) {
    vector<DistTag> dist(graph.size(), DistTag(K));
    dist[start].insert(0);

    TIMES(_, static_cast<int>(graph.size())*K) {
        TIMES(i, static_cast<int>(graph.size())) {
            DistTag &dt = dist[i];
            if(dt.newbie.size() == 0) continue;
            FOREACH(it, graph[i]) {
                assert(it->from == i);
                FOREACH(nit, dt.newbie) {
                    //cout << "insert " << i << ' ' << it->to << endl;
                    dist[it->to].insert(*nit + it->cost);
                }
            }
            dt.flush();
        }
    }
    pair<int,Cost> res(0, 0);
    vector<Cost> costs;
    TIMES(i, P) {
        FOREACH(it, dist[(N-1)*P+i].buf) {
            costs.push_back(*it);
        }
    }
    sort(costs.begin(), costs.end());
    TIMES(i, min(K, static_cast<int>(costs.size()))) {
        if(costs[i] == INF) break;
        res.first++;
        res.second += costs[i];
    }
    return res;
}

pair<int,Cost> solve(int N) {
    vector<int> color_of(N);
    TIMES(i, N) {
        cin >> color_of[i];
        --color_of[i];
    }
    int M;
    cin >> M;
    vector<Edge> edges(M);
    TIMES(i, M) {
        Edge &e = edges[i];
        cin >> e.from >> e.to >> e.cost;
        --e.from; --e.to;
    }
    int K;
    cin >> K;
    vector<int> prohibited;
    {
        string str;
        cin >> str;
        FOREACH(it, str) {
            prohibited.push_back(*it - '0' - 1);
        }
    }
    const int P = prohibited.size();
    vector<vector<int> > next_prohibited_pos(P, vector<int>(4, 0));
    {
        int shadow = 0;
        TIMES(i, P) {
            next_prohibited_pos[i][prohibited[i]] = i+1;
            if(i > 0) {
                TIMES(j, 4) {
                    if(j != prohibited[i]) next_prohibited_pos[i][j] = next_prohibited_pos[shadow][j];
                }
                shadow = next_prohibited_pos[shadow][prohibited[i]];
            }
        }
    }

    const int start = 0+next_prohibited_pos[0][color_of[0]];
    vector<EdgeList> graph(N*P);
    FOREACH(it, edges) {
        TIMES(i, P) {
            // Cannot reach this state.
            if(i > 0 && prohibited[i-1] != color_of[it->from]) continue;

            int np = next_prohibited_pos[i][color_of[it->to]];
            if(np < P) {
                graph[it->from*P+i].push_back(Edge(it->from*P+i, it->to*P+np, it->cost));
                //cout << it->from << ' ' << i << ' ' << it->to << ' ' << np << endl;
            }
        }
    }

    // Remove all unreachable nodes.
    // It causes fake negative loop detection.
    vector<unsigned char> reachable(N*P, 0);
    check_reachable(start, graph, reachable);
    TIMES(i, N*P) {
        if(!reachable[i]) graph[i].clear();
    }

    // Check if it has negative loop
    vector<Cost> dist(N*P, INF);
    dist[start] = 0;
    TIMES(_, N*P) {
        relax(graph, dist);
    }
    vector<Cost> tmp_last(P);
    TIMES(i, P) {
        tmp_last[i] = dist[(N-1)*P+i];
    }
    TIMES(_, N*P) {
        relax(graph, dist);
        TIMES(i, P) {
            if(dist[(N-1)*P+i] != tmp_last[i]) return make_pair(-1, -1);
        }
    }

    pair<int,Cost> res = search(start, graph, N, P, K);
    return res;
}

int main() {
    cin.tie(0);
    ios::sync_with_stdio(0);

    int N;
    while(cin >> N) {
        if(!N) break;
        pair<int,Cost> ans = solve(N);
        if(ans.first == -1) cout << -1 << endl;
        else cout << ans.first << ' ' << ans.second << endl;
    }
    return 0;
}
accuracy: 0.23076923076923078
time_ms: 20
memory_kb: 1460
final_rank: 13

code_snippet: #include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <queue>
#include <string>
#include <map>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

typedef int Weight;
struct Edge {
  int src;
  int dest;
  Weight weight;
  Edge(int src, int dest, Weight weight) : src(src), dest(dest), weight(weight) {;}
  bool operator<(const Edge &rhs) const {
    return weight > rhs.weight;
  }
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

void PrintMatrix(const Matrix &matrix) {
  for (int y = 0; y < (int)matrix.size(); y++) {
    for (int x = 0; x < (int)matrix[y].size(); x++) {
      printf("%d ", matrix[y][x]);
    }
    puts("");
  }
}

bool end[1100];
static const Weight INF = 2000000000LL;
Weight BellmanFord(const Graph &g, Array &dist) {
  const int n = g.size();
  dist = Array(n, 0x0f0f0f0f);
  dist[0] = 0;
  REP(iter, n) {
    bool e = true;
    REP(i, n) {
      REP(j, g[i].size()) {
        int to = g[i][j].dest;
        Weight ncost = dist[i] + g[i][j].weight;
        if (dist[to] > ncost) {
          dist[to] = ncost;
          e = false;
        }
      }
    }
    if (e) { return 0; }
  }
  return -INF;
}

int n, m, k, len;
int color[110];
char ban[1000];
int memo[20][20];

int OneMove(int pattern, int c) {
  if (ban[pattern] == c) { return pattern + 1; }
  if (memo[pattern][c] != -1) { return memo[pattern][c]; }
  deque<int> now;
  REP(i, pattern) { now.push_back(ban[i]); }
  now.push_back(c);
  while (!now.empty()) {
    now.pop_front();
    REP(i, now.size()) {
      if (now[i] != ban[i]) { goto next; }
    }
    break;
next:;
  }
  return memo[pattern][c] = now.size();
}

Graph Expand(Graph g) {
  MEMSET(memo, -1);
  vector<bool> visit(n * len, false);
  queue<pair<int, int> > que;
  int first = color[0] == ban[0] ? 1 : 0;
  que.push(make_pair(0, first));
  Graph ret(n * len);
  if (len == first) { return ret; }
  while (!que.empty()) {
    int from = que.front().first;
    int pattern = que.front().second;
    que.pop();
    if (visit[from * len + pattern]) { continue; }
    visit[from * len + pattern] = true;
    FORIT(it, g[from]) {
      int to = it->dest;
      int c = color[to];
      int npattern = OneMove(pattern, c);
      if (npattern == len) { continue; }
      ret[from * len + pattern].push_back(Edge(from * len + pattern, to * len + npattern, it->weight));
      que.push(make_pair(to, npattern));
    }
  }
  return ret;
}

Graph revG(Graph g) {
  Graph ret(g.size());
  REP(i, g.size()) {
    FORIT(it, g[i]) {
      ret[it->dest].push_back(Edge(it->dest, it->src, it->weight));
    }
  }
  return ret;
}

void dfs(const Graph &g, int from, vector<bool> &visit) {
  if (visit[from]) { return; }
  visit[from] = true;
  FORIT(it, g[from]) {
    dfs(g, it->dest, visit);
  }
}

Graph Erase(Graph g) {
  MEMSET(end, false);
  vector<bool> visit1(1010, 0);
  vector<bool> visit2(1010, 0);
  Graph rev = revG(g);
  dfs(g, color[0] == ban[0], visit1);
  if (len == 1 && color[0] == ban[0]) { visit1[1] = false; }
  REP(i, len) { dfs(rev, (n - 1) * len + i, visit2); }
  int m = 0;
  map<int, int> mapto;
  REP(i, n * len) {
    if (!visit1[i] || !visit2[i]) { continue; }
    if (i >= (n - 1) * len) { end[m] = true; }
    mapto[i] = m++;
  }
  Graph ret(m);
  REP(i, n * len) {
    if (!mapto.count(i)) { continue; }
    int from = mapto[i];
    FORIT(it, g[i]) {
      if (!mapto.count(it->dest)) { continue; }
      int to = mapto[it->dest];
      ret[from].push_back(Edge(from, to, it->weight));
    }
  }
  return ret;
}

vector<int> dists[1010];
pair<int, int> calc(const Graph &g) {
  if (g.size() == 0) { return make_pair(0, 0); }
  Array dist;
  int v = BellmanFord(g, dist);
  if (v == -INF) { return make_pair(-1, -1); }
  priority_queue<Edge> que;
  que.push(Edge(0, 0, 0));
  REP(i, 1010) { dists[i].clear(); }
  vector<int> ans;
  while (!que.empty()) {
    Edge e = que.top();
    que.pop();
    int from = e.dest;
    if ((int)dists[from].size() == k) { continue; }
    dists[from].push_back(e.weight);
    if (end[from]) { ans.push_back(e.weight + dist[from]); }
    FORIT(it, g[from]) {
      int to = it->dest;
      int ncost = it->weight + e.weight + (dist[from] - dist[to]);
      que.push(Edge(from, to, ncost));
    }
  }
  pair<int, int> ret = make_pair(0, 0);
  sort(ans.begin(), ans.end());
  ret.first = min(k, (int)ans.size());
  REP(i, ret.first) { ret.second += ans[i]; }
  return ret;
}

int main() {
  while (scanf("%d", &n), n) {
    REP(i, n) { scanf("%d", &color[i]); }
    scanf("%d", &m);
    Graph g(n);
    REP(i, m) {
      int f, t, c;
      scanf("%d %d %d", &f, &t, &c);
      f--; t--;
      g[f].push_back(Edge(f, t, c));
    }
    scanf("%d", &k);
    scanf("%s", ban);
    len = strlen(ban);
    REP(i, len) { ban[i] -= '0'; }
    g = Expand(g);
    g = Erase(g);
    pair<int, int> ans = calc(g);
    if (ans.first == -1) {
      puts("-1");
    } else {
      printf("%d %d\n", ans.first, ans.second);
    }
  }
}
accuracy: 1
time_ms: 170
memory_kb: 1948
final_rank: 2

code_snippet: #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

struct edge{ int v,cost; };

struct Xnode{
	int u,t;
	bool operator<(const Xnode &X)const{ return u<X.u || u==X.u && t<X.t; }
};

struct Xedge{
	Xnode X;
	int cost;
};

int n,color[100],K,len;
vector<edge> G[100];
char pttn[11];

bool input(){
	scanf("%d",&n);
	if(n==0) return false;
	rep(u,n){
		G[u].clear();
		scanf("%d",color+u);
	}
	int m; scanf("%d",&m);
	rep(i,m){
		int u,v,cost; scanf("%d%d%d",&u,&v,&cost); u--; v--;
		G[u].push_back((edge){v,cost});
	}
	scanf("%d%s",&K,pttn);
	len=strlen(pttn);
	return true;
}

vector<Xedge> XG[100][10],XG_rev[101][10];
void build_XG(){
	rep(u,n+1) rep(t,max(len,2)) {
		XG[u][t].clear();
		XG_rev[u][t].clear();
	}

	rep(u,n) rep(t,len) rep(i,G[u].size()) {
		int v=G[u][i].v,cost=G[u][i].cost;

		char tmp[12]={};
		strncpy(tmp,pttn,t);
		tmp[t]=color[v]+'0';
		int t_next;
		for(t_next=t+1;strncmp(pttn,tmp+(t+1)-t_next,t_next);t_next--);

		if(t_next<len){
			XG[u][t].push_back((Xedge){(Xnode){v,t_next},cost});
			XG_rev[v][t_next].push_back((Xedge){(Xnode){u,t},cost});
		}
	}
	rep(t,len) XG_rev[n][0].push_back((Xedge){(Xnode){n-1,t},0});
}

bool vis[101][10];
bool dfs(int u,int t){
	vis[u][t]=true;
	rep(i,XG[u][t].size()){
		const Xedge &e=XG[u][t][i];
		int v=e.X.u,t_next=e.X.t;
		if(!vis[v][t_next]) dfs(v,t_next);
	}
}

bool vis_rev[101][10];
bool dfs_rev(int v,int t){
	vis_rev[v][t]=true;
	rep(i,XG_rev[v][t].size()){
		const Xedge &e=XG_rev[v][t][i];
		int u=e.X.u,t_prev=e.X.t;
		if(!vis_rev[u][t_prev]) dfs_rev(u,t_prev);
	}
}

void delete_Xnodes(){
	rep(u,n+1) rep(t,len) vis[u][t]=vis_rev[u][t]=false;

	int t0=(pttn[0]==color[0]+'0'?1:0);
	dfs(0,t0);
	dfs_rev(n,0);

	rep(u,n) rep(t,len) {
		if(!vis[u][t] || !vis_rev[u][t]){
			XG[u][t].clear();
		}
		else{
			rep(i,XG[u][t].size()){
				const Xedge &e=XG[u][t][i];
				int v=e.X.u,t_next=e.X.t;
				if(!vis[v][t_next] || !vis_rev[v][t_next]){
					XG[u][t].erase(XG[u][t].begin()+i);
					i--;
				}
			}
		}
	}
}

int pot[101][10];
bool calc_potential(){
	rep(u,n+1) rep(t,len) pot[u][t]=0;

	rep(c,n*len){
		rep(u,n+1) rep(t,len) rep(i,XG[u][t].size()) {
			const Xedge &e=XG[u][t][i];
			int v=e.X.u,t_next=e.X.t,cost=e.cost;
			if(pot[u][t]+cost<pot[v][t_next]){
				pot[v][t_next]=pot[u][t]+cost;
				if(c==n*len-1){
					puts("-1");
					return false;
				}
			}
		}
	}
	return true;
}

void Kth_shortest_path(){
	int nd[100][10]={},d[100][10][10];
	int t0=(pttn[0]==color[0]+'0'?1:0);

	priority_queue< pair<int,Xnode> > Q;
	Q.push(make_pair(0,(Xnode){0,t0}));
	while(!Q.empty()){
		int d_now=-Q.top().first;
		int u=Q.top().second.u,t=Q.top().second.t; Q.pop();

		if(nd[u][t]==K) continue;
		d[u][t][nd[u][t]++]=d_now;

		rep(i,XG[u][t].size()){
			const Xedge &e=XG[u][t][i];
			int v=e.X.u,t_next=e.X.t,cost=e.cost;
			if(nd[v][t_next]<K){
				int d_next=d_now+cost+pot[u][t]-pot[v][t_next];
				Q.push(make_pair(-d_next,(Xnode){v,t_next}));
			}
		}
	}

	vector<int> ans;
	rep(t,len) rep(i,nd[n-1][t]) ans.push_back(d[n-1][t][i]-pot[0][t0]+pot[n-1][t]);
	sort(ans.begin(),ans.end());

	int n_ans=min((int)ans.size(),K),ans_sum=0;
	rep(i,n_ans) ans_sum+=ans[i];
	printf("%d %d\n",n_ans,ans_sum);
}

int main(){
	while(input()){
		build_XG();
		delete_Xnodes();
		if(!calc_potential()) continue;
		Kth_shortest_path();
	}
	return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 2196
final_rank: 8

code_snippet: #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

struct edge{ int v,cost; };

// g£µ½OtÉ¨¯é¸_
struct Xnode{
	int u,t; // R[ÌÔ, pttn Ì½¶ÚÜÅ}b`µ½©
	bool operator<(const Xnode &X)const{ return u<X.u || u==X.u && t<X.t; }
};

// g£µ½OtÉ¨¯éÓ
struct Xedge{
	Xnode X;
	int cost;
};

int n,color[100],K,len;
vector<edge> G[100]; // ³ÌOt
char pttn[11];

bool input(){
	scanf("%d",&n);
	if(n==0) return false;
	rep(u,n){
		G[u].clear();
		scanf("%d",color+u);
	}
	int m; scanf("%d",&m);
	rep(i,m){
		int u,v,cost; scanf("%d%d%d",&u,&v,&cost); u--; v--;
		G[u].push_back((edge){v,cost});
	}
	scanf("%d%s",&K,pttn);
	len=strlen(pttn);
	return true;
}

vector<Xedge> XG[100][10],XG_rev[101][10]; // g£µ½Ot, XG ÌtOt
void build_XG(){
	rep(u,n+1) rep(t,max(len,2)) {
		XG[u][t].clear();
		XG_rev[u][t].clear();
	}

	rep(u,n) rep(t,len) rep(i,G[u].size()) {
		int v=G[u][i].v,cost=G[u][i].cost;

		char tmp[12]={};
		strncpy(tmp,pttn,t);
		tmp[t]=color[v]+'0';
		int t_next;
		for(t_next=t+1;strncmp(pttn,tmp+(t+1)-t_next,t_next);t_next--);

		if(t_next<len){
			XG[u][t].push_back((Xedge){(Xnode){v,t_next},cost});
			XG_rev[v][t_next].push_back((Xedge){(Xnode){u,t},cost});
		}
	}
	// XG_rev Ìn_½¿ ( XG ÌI_½¿ ) ðêÂÉÜÆßé
	rep(t,len) XG_rev[n][0].push_back((Xedge){(Xnode){n-1,t},0});
}

bool vis[101][10]; // XG É¨¢Än_ (0, t0) ©çHè¯é Xnode ÌW
bool dfs(int u,int t){
	vis[u][t]=true;
	rep(i,XG[u][t].size()){
		const Xedge &e=XG[u][t][i];
		int v=e.X.u,t_next=e.X.t;
		if(!vis[v][t_next]) dfs(v,t_next);
	}
}

bool vis_rev[101][10]; // XG É¨¢ÄI_½¿ (n-1, t) (0 < t < len) ©çHè¯é Xnode ÌW
bool dfs_rev(int v,int t){
	vis_rev[v][t]=true;
	rep(i,XG_rev[v][t].size()){
		const Xedge &e=XG_rev[v][t][i];
		int u=e.X.u,t_prev=e.X.t;
		if(!vis_rev[u][t_prev]) dfs_rev(u,t_prev);
	}
}

// Bellman-Ford Éæéë»èðh®½ßÉKvÌÈ¢ Xnode ð XG ©çí·é
void delete_Xnodes(){
	rep(u,n+1) rep(t,len) vis[u][t]=vis_rev[u][t]=false;

	int t0=(pttn[0]==color[0]+'0'?1:0);
	dfs(0,t0);
	dfs_rev(n,0);

	rep(u,n) rep(t,len) {
		if(!vis[u][t] || !vis_rev[u][t]){
			XG[u][t].clear();
		}
		else{
			rep(i,XG[u][t].size()){
				const Xedge &e=XG[u][t][i];
				int v=e.X.u,t_next=e.X.t;
				if(!vis[v][t_next] || !vis_rev[v][t_next]){
					XG[u][t].erase(XG[u][t].begin()+i);
					i--;
				}
			}
		}
	}
}

int pot[101][10];
// Bellman-Ford @ðp¢Ä|eVðvZ
bool calc_potential(){
	rep(u,n+1) rep(t,len) pot[u][t]=0;

	rep(c,n*len){
		rep(u,n+1) rep(t,len) rep(i,XG[u][t].size()) {
			const Xedge &e=XG[u][t][i];
			int v=e.X.u,t_next=e.X.t,cost=e.cost;
			if(pot[u][t]+cost<pot[v][t_next]){
				pot[v][t_next]=pot[u][t]+cost;
				if(c==n*len-1){
					puts("-1");
					return false;
				}
			}
		}
	}
	return true;
}

void Kth_shortest_path(){
	int nd[100][10]={},d[100][10][10];
	int t0=(pttn[0]==color[0]+'0'?1:0);

	priority_queue< pair<int,Xnode> > Q;
	Q.push(make_pair(0,(Xnode){0,t0}));
	while(!Q.empty()){
		int d_now=-Q.top().first;
		int u=Q.top().second.u,t=Q.top().second.t; Q.pop();

		if(nd[u][t]==K) continue;
		d[u][t][nd[u][t]++]=d_now;

		rep(i,XG[u][t].size()){
			const Xedge &e=XG[u][t][i];
			int v=e.X.u,t_next=e.X.t,cost=e.cost;
			if(nd[v][t_next]<K){
				int d_next=d_now+cost+pot[u][t]-pot[v][t_next];
				Q.push(make_pair(-d_next,(Xnode){v,t_next}));
			}
		}
	}

	vector<int> ans;
	rep(t,len) rep(i,nd[n-1][t]) ans.push_back(d[n-1][t][i]-pot[0][t0]+pot[n-1][t]);
	sort(ans.begin(),ans.end());

	int n_ans=min((int)ans.size(),K),ans_sum=0;
	rep(i,n_ans) ans_sum+=ans[i];
	printf("%d %d\n",n_ans,ans_sum);
}

int main(){
	while(input()){
		build_XG();
		delete_Xnodes();
		if(!calc_potential()) continue;
		Kth_shortest_path();
	}
	return 0;
}
accuracy: 1
time_ms: 640
memory_kb: 2192
final_rank: 7

code_snippet: #include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>

#define rep(i,n) for(int i=0;i<(n);i++)

using namespace std;

const int INF=1<<29;

struct edge{ int v,cost; };

// g£µ½OtÉ¨¯é¸_
struct Xnode{
	int u,t; // R[ÌÔ, pttn Ì½¶ÚÜÅ}b`µ½©
	bool operator<(const Xnode &X)const{ return u<X.u || u==X.u && t<X.t; }
};

// g£µ½OtÉ¨¯éÓ
struct Xedge{
	Xnode X;
	int cost;
};

int n,color[100],K,len;
vector<edge> G[100]; // ³ÌOt
char pttn[11];

bool input(){
	scanf("%d",&n);
	if(n==0) return false;
	rep(u,n){
		G[u].clear();
		scanf("%d",color+u);
	}
	int m; scanf("%d",&m);
	rep(i,m){
		int u,v,cost; scanf("%d%d%d",&u,&v,&cost); u--; v--;
		G[u].push_back((edge){v,cost});
	}
	scanf("%d%s",&K,pttn);
	len=strlen(pttn);
	return true;
}

vector<Xedge> XG[101][10],XG_rev[101][10]; // g£µ½Ot, XG ÌtOt
void build_XG(){
	rep(u,n+1) rep(t,max(len,2)) {
		XG[u][t].clear();
		XG_rev[u][t].clear();
	}

	rep(u,n) rep(t,len) rep(i,G[u].size()) {
		int v=G[u][i].v,cost=G[u][i].cost;

		char tmp[12]={};
		strncpy(tmp,pttn,t);
		tmp[t]=color[v]+'0';
		int t_next;
		for(t_next=t+1;strncmp(pttn,tmp+(t+1)-t_next,t_next);t_next--);

		if(t_next<len){
			XG[u][t].push_back((Xedge){(Xnode){v,t_next},cost});
			XG_rev[v][t_next].push_back((Xedge){(Xnode){u,t},cost});
		}
	}
	// XG_rev Ìn_½¿ ( XG ÌI_½¿ ) ðêÂÉÜÆßé
	rep(t,len) XG_rev[n][0].push_back((Xedge){(Xnode){n-1,t},0});
	// |eVvZpÌ super source
	rep(u,n) rep(t,len) XG[n][0].push_back((Xedge){(Xnode){u,t},0});
}

bool vis[101][10]; // XG É¨¢Än_ (0, t0) ©çHè¯é Xnode ÌW
bool dfs(int u,int t){
	vis[u][t]=true;
	rep(i,XG[u][t].size()){
		const Xedge &e=XG[u][t][i];
		int v=e.X.u,t_next=e.X.t;
		if(!vis[v][t_next]) dfs(v,t_next);
	}
}

bool vis_rev[101][10]; // XG É¨¢ÄI_½¿ (n-1, t) (0 < t < len) ©çHè¯é Xnode ÌW
bool dfs_rev(int v,int t){
	vis_rev[v][t]=true;
	rep(i,XG_rev[v][t].size()){
		const Xedge &e=XG_rev[v][t][i];
		int u=e.X.u,t_prev=e.X.t;
		if(!vis_rev[u][t_prev]) dfs_rev(u,t_prev);
	}
}

// Bellman-Ford Éæéë»èðh®½ßÉKvÌÈ¢ Xnode ð XG ©çí·é
void delete_Xnodes(){
	rep(u,n+1) rep(t,len) vis[u][t]=vis_rev[u][t]=false;

	int t0=(pttn[0]==color[0]+'0'?1:0);
	dfs(0,t0);
	dfs_rev(n,0);

	rep(u,n) rep(t,len) {
		if(!vis[u][t] || !vis_rev[u][t]){
			XG[u][t].clear();
		}
		else{
			rep(i,XG[u][t].size()){
				const Xedge &e=XG[u][t][i];
				int v=e.X.u,t_next=e.X.t;
				if(!vis[v][t_next] || !vis_rev[v][t_next]){
					XG[u][t].erase(XG[u][t].begin()+i);
					i--;
				}
			}
		}
	}
}

int pot[101][10];
// Bellman-Ford @ðp¢Ä|eVðvZ
bool calc_potential(){
	rep(u,n+1) rep(t,len) pot[u][t]=INF;
	pot[n][0]=0;

	rep(c,n*len){
		rep(u,n+1) rep(t,len) {
			if(pot[u][t]==INF) continue;
			rep(i,XG[u][t].size()){
				const Xedge &e=XG[u][t][i];
				int v=e.X.u,t_next=e.X.t,cost=e.cost;
				if(pot[u][t]+cost<pot[v][t_next]){
					pot[v][t_next]=pot[u][t]+cost;
					if(c==n*len-1){
						puts("-1");
						return false;
					}
				}
			}
		}
	}
	return true;
}

void Kth_shortest_path(){
	int nd[100][10]={},d[100][10][10];
	int t0=(pttn[0]==color[0]+'0'?1:0);

	priority_queue< pair<int,Xnode> > Q;
	Q.push(make_pair(0,(Xnode){0,t0}));
	while(!Q.empty()){
		int d_now=-Q.top().first;
		int u=Q.top().second.u,t=Q.top().second.t; Q.pop();

		if(nd[u][t]==K) continue;
		d[u][t][nd[u][t]++]=d_now;

		rep(i,XG[u][t].size()){
			const Xedge &e=XG[u][t][i];
			int v=e.X.u,t_next=e.X.t,cost=e.cost;
			if(nd[v][t_next]<K){
				int d_next=d_now+cost+pot[u][t]-pot[v][t_next];
				Q.push(make_pair(-d_next,(Xnode){v,t_next}));
			}
		}
	}

	vector<int> ans;
	rep(t,len) rep(i,nd[n-1][t]) ans.push_back(d[n-1][t][i]-pot[0][t0]+pot[n-1][t]);
	sort(ans.begin(),ans.end());

	int n_ans=min((int)ans.size(),K),ans_sum=0;
	rep(i,n_ans) ans_sum+=ans[i];
	printf("%d %d\n",n_ans,ans_sum);
}

int main(){
	while(input()){
		build_XG();
		delete_Xnodes();
		if(!calc_potential()) continue;
		Kth_shortest_path();
	}
	return 0;
}
accuracy: 1
time_ms: 690
memory_kb: 2192
final_rank: 9

code_snippet: #include<iostream>
#include<sstream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
using namespace std;

#define rep(i,n) for(int i=0;i<(int)n;i++)
#define fr(i,c) for(__typeof(c.begin()) i=c.begin();i!=c.end();i++)
#define pb push_back
#define mp make_pair
#define all(c) c.begin(),c.end()
#define dbg(x) cerr<<#x<<" = "<<(x)<<endl

typedef vector<int> vi;
typedef pair<int,int> pi;
typedef long long ll;
const int inf=(int)1e9;
const double EPS=1e-9, INF=1e12;

typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;

vi k_shortestPath(const Graph &g, int s, int t, int k,int *h) {
  int n=g.size();
  vi dist[n];
  priority_queue<Edge> Q; Q.push(Edge(-1, s, 0));
  while (!Q.empty()) {
    Edge e = Q.top(); Q.pop();
    if (dist[e.dst].size() >= k) continue;
    dist[e.dst].push_back(e.weight);
    fr(f, g[e.dst]) Q.push(Edge(f->src, f->dst, f->weight+e.weight+h[f->src]-h[f->dst]));
  }
  rep(i,dist[t].size())dist[t][i]+=h[t]-h[s];
  return dist[t];
}
int *buildFail(char *p) {
  int m = strlen(p);
  int *fail = new int[m+1];
  int j = fail[0] = -1;
  for (int i = 1; i <= m; ++i) {
    while (j >= 0 && p[j] != p[i-1]) j = fail[j];
    fail[i] = ++j;
  }
  return fail;
}

int n,col[100],m,a[1000],b[1000],c[1000],k;
char ptn[20];
int V,s,t,h[1111];
Graph G,rG;

bool v[1111],rv[1111];
void dfs(int c,const Graph &g,bool *v){
	v[c]=1;
	fr(i,g[c])if(!v[i->dst])dfs(i->dst,g,v);
}
bool calc_potential(){
	fill(h,h+V+1,0);
	rep(k,V)rep(i,V)if(v[i]&&rv[i])fr(e,G[i]){
		if(h[e->dst]>h[e->src]+e->weight){
			h[e->dst]=h[e->src]+e->weight;
			if(k==V-1)return 0;
		}
	}
	return 1;
}
inline void push(Graph &g,int src,int dst,int weight){
	g[src].pb(Edge(src,dst,weight));
}
bool make_graph(){
	int *fail=buildFail(ptn), len=strlen(ptn);
	G.clear(); rG.clear();
	V=n*(len+1)+1;
	s=0; t=V-1;
	while(s>=0&&ptn[s]-'0'!=col[0])s=fail[s];
	if(++s>=len)return 0;
	G.resize(V); rG.resize(V);
	
	vector<vector<pi> > e(n);
	rep(i,m)e[a[i]-1].pb(mp(b[i]-1,c[i]));
	
	rep(i,n)rep(j,len+1){
		fr(k,e[i]){
			int to=j;
			while(to>=0&&ptn[to]-'0'!=col[k->first])to=fail[to];
			if(++to>=len)continue;
			push(G,i*(len+1)+j,k->first*(len+1)+to,k->second);
			push(rG,k->first*(len+1)+to,i*(len+1)+j,0);
		}
	}
	rep(j,len){
		push(G,(n-1)*(len+1)+j,t,0);
		push(rG,t,(n-1)*(len+1)+j,0);
	}
	rep(i,V)v[i]=rv[i]=0;
	dfs(s,G,v); dfs(t,rG,rv);
	return v[t]&&rv[s];
}

int main(){
	while(cin>>n,n){
		rep(i,n)cin>>col[i];
		cin>>m;
		rep(i,m)cin>>a[i]>>b[i]>>c[i];
		cin>>k>>ptn;
		
		if(!make_graph()){
			cout<<"0 0"<<endl; continue;
		}
		if(!calc_potential()){
			cout<<-1<<endl; continue;
		}
		vi ans=k_shortestPath(G,s,t,k,h);
		int sum=0;
		rep(i,ans.size())sum+=ans[i];
		cout<<ans.size()<<" "<<sum<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 620
memory_kb: 1976
final_rank: 5

code_snippet: #include<iostream>
#include<sstream>
#include<vector>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<complex>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cassert>
using namespace std;

#define rep(i,n) for(int i=0;i<(int)n;i++)
#define fr(i,c) for(__typeof(c.begin()) i=c.begin();i!=c.end();i++)
#define pb push_back
#define mp make_pair
#define all(c) c.begin(),c.end()
#define dbg(x) cerr<<#x<<" = "<<(x)<<endl

typedef vector<int> vi;
typedef pair<int,int> pi;
typedef long long ll;
const int inf=(int)1e9;
const double EPS=1e-9, INF=1e12;

typedef int Weight;
struct Edge {
  int src, dst;
  Weight weight;
  Edge(int src, int dst, Weight weight) :
    src(src), dst(dst), weight(weight) { }
};
bool operator < (const Edge &e, const Edge &f) {
  return e.weight != f.weight ? e.weight > f.weight : // !!INVERSE!!
    e.src != f.src ? e.src < f.src : e.dst < f.dst;
}
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;
// simpler method
vi k_shortestPath(const Graph &g, int s, int t, int k,int *h) {
  int n=g.size();
  vi dist[n];
  priority_queue<Edge> Q; Q.push(Edge(-1, s, 0));
  while (!Q.empty()) {
    Edge e = Q.top(); Q.pop();
    if (dist[e.dst].size() >= k) continue;
    dist[e.dst].push_back(e.weight);
    fr(f, g[e.dst]) Q.push(Edge(f->src, f->dst, f->weight+e.weight+h[f->src]-h[f->dst]));
  }
  rep(i,dist[t].size())dist[t][i]+=h[t]-h[s];
  return dist[t];
}
int *buildFail(char *p) {
  int m = strlen(p);
  int *fail = new int[m+1];
  int j = fail[0] = -1;
  for (int i = 1; i <= m; ++i) {
    while (j >= 0 && p[j] != p[i-1]) j = fail[j];
    fail[i] = ++j;
  }
  return fail;
}
int match(char *t, char *p, int *fail) {
  int n = strlen(t), m = strlen(p);
  int count = 0;
  for (int i = 0, k = 0; i < n; ++i) {
    while (k >= 0 && p[k] != t[i]) k = fail[k];
    if (++k >= m) {
      ++count; // match at t[i-m+1 .. i]
      k = fail[k];
    }
  }
  return count;
}


bool make_graph();
bool calc_potential();

int n,col[100],m,a[1000],b[1000],c[1000],k;
char ptn[20];
int V,s,t,h[1111];
Graph G,rG;
bool v[1111],rv[1111];

int main(){
	while(cin>>n,n){
		rep(i,n)cin>>col[i];
		cin>>m;
		rep(i,m)cin>>a[i]>>b[i]>>c[i];
		cin>>k>>ptn;
		
		if(!make_graph()){
			cout<<"0 0"<<endl; continue;
		}
		if(!calc_potential()){
			cout<<-1<<endl; continue;
		}
		vi ans=k_shortestPath(G,s,t,k,h);
		int sum=0;
		rep(i,ans.size())sum+=ans[i];
		cout<<ans.size()<<" "<<sum<<endl;
	}
	return 0;
}

void dfs(int c,const Graph &g,bool *v){
	v[c]=1;
	fr(i,g[c])if(!v[i->dst])dfs(i->dst,g,v);
}
bool calc_potential(){
	fill(h,h+V+1,0);
	rep(k,V)rep(i,V)if(v[i]&&rv[i])fr(e,G[i]){
		if(h[e->dst]>h[e->src]+e->weight){
			h[e->dst]=h[e->src]+e->weight;
			if(k==V-1) return 0; // negative cycle
		}
	}
	return 1;
}
inline void push(Graph &g,int src,int dst,int weight){
	g[src].pb(Edge(src,dst,weight));
}
bool make_graph(){
	int *fail=buildFail(ptn), len=strlen(ptn);
	G.clear(); rG.clear();
	V=n*(len+1)+1;
	s=0; t=V-1;
	while(s>=0&&ptn[s]-'0'!=col[0])s=fail[s];
	if(++s>=len)return 0;
	G.resize(V); rG.resize(V);
	
	vector<vector<pi> > e(n);
	rep(i,m)e[a[i]-1].pb(mp(b[i]-1,c[i]));
	
	rep(i,n)rep(j,len+1){
		fr(k,e[i]){
			int to=j;
			while(to>=0&&ptn[to]-'0'!=col[k->first])to=fail[to];
			if(++to>=len)continue;
			push(G,i*(len+1)+j,k->first*(len+1)+to,k->second);
			push(rG,k->first*(len+1)+to,i*(len+1)+j,0);
		}
	}
	rep(j,len){
		push(G,(n-1)*(len+1)+j,t,0);
		push(rG,t,(n-1)*(len+1)+j,0);
	}
	/*
	dbg(len); dbg(t);
	rep(i,n)rep(j,len+1){
		cerr<<"i: "<<i<<" j: "<<j<<endl;
		fr(k,G[i*(len+1)+j])cerr<<k->src<<" "<<k->dst<<" "<<k->weight<<endl;
	}
	*/
	rep(i,V)v[i]=rv[i]=0;
	dfs(s,G,v); dfs(t,rG,rv);
	return v[t]&&rv[s];
}
accuracy: 1
time_ms: 620
memory_kb: 1976
final_rank: 5