Problem:
一日乗車券
某国に住む大学生D氏は，国民的ギタリストA氏の大ファンで，この夏都心で行われるライブに行こうと考えている．
しかし，D氏は辺境の地に住んでいるため，交通費がかかることがとても不安だった．
そんなとき彼は，JAGという組織から安価で販売されている「1Dayパスポート」の存在を知った．
JAG (Journey Administrative Group) は，D氏が住む国に存在するいくつかの鉄道会社を統括する組織である．
JAGは，全国に複数の駅を持ち，それらの間を結ぶ路線を整備している．
各路線は，JAGに所属する会社の内いずれか1社により管理されており，2駅間を途中駅無しで双方向に結んでいる．
また各路線には，利用する際の運賃と所要時間が定まっている (これらはどちら向きに移動する場合でも等しい)．
JAGのダイヤはシンプルに作られており，列車は毎時0分に駅に発着する．
またJAGの各駅は，極めて賢くデザインされており，路線の乗り換えにかかる時間は無視することができる．
移動に必要な交通費は運賃の単純な合計となる.
1Dayパスポートは，JAGが昨今の経営難を脱するために販売し始めた，乗り放題パスポートである．
JAGは，何種類かの1Dayパスポートを販売している．
各パスポートは，JAGが指定する販売価格で購入することができる．
またパスポートには，JAGに所属する会社名がいくつか書かれており，これらの会社が管理する全ての路線が1日間 (追加料金無しで) 乗り放題になる．
パスポートは，いくつでも購入することができ，複数のパスポートを併用することができる．
ただし，パスポートに書かれていない会社の管理路線を通る場合，その路線の運賃は通常通り必要となる．
D氏は，1Dayパスポートをうまく使い，なるべくお金をかけずライブ会場まで行きたいと考えている．
また，彼は宿泊で余計にお金をかけるのが嫌なので，この国の1日である$H$時間以下でライブ会場まで辿り着きたいと考えている．
しかし，彼は計算が得意ではないため，同じ大学の友人でプログラミングが得意なあなたに助けを求めて来た．
困っているD氏のために，次のようなプログラムを書いてあげよう．
JAGの路線情報と1Dayパスポートの情報が与えられたとき，D氏の最寄り駅からライブ会場の最寄り駅へ，$H$時間以下で移動するための最小費用 (パスポート代と運賃の合計の最小) を求めるプログラムを作成せよ．
$H$時間以下で到達できない場合や，ライブ会場へ到達する経路がない場合は，-1を出力せよ．
Input
入力は，複数のデータセットから構成され，1つの入力に含まれるデータセットの数は150以下である．
各データセットの形式は次の通りである．
$N$ $M$ $H$ $K$
$a_1$ $b_1$ $c_1$ $h_1$ $r_1$
...
$a_M$ $b_M$ $c_M$ $h_M$ $r_M$
$S$ $T$
$P$
$l_1$ $d_1$ $k_{1,1}$ ... $k_{1,l_1}$
...
$l_P$ $d_P$ $k_{P,1}$ ... $k_{P,l_P}$
入力は全て整数値で与えられる．
まず，JAGの路線情報が与えられる．
$N$ ($2 \le N \le 100$) は駅の数，$M$ ($1 \le M \le 500$) は路線の数，$H$ ($1 \le H \le 24$) は1日の時間，$K$ ($1 \le K \le 8$) はJAGに所属する会社数を表す．
各駅には，$1, 2, \ldots, N$ と番号がついている．
また，各会社には，$1, 2, \ldots, K$ と番号がついている．
続いて $M$ 行にわたって路線情報が入力される．
$a_i$ と $b_i$ ($1 \le a_i \lt b_i \le N$) が $i$ 番目の路線がつないでいる2つの駅を表す．
$c_i$ ($1 \le c_i \le 10{,}000$) は $i$ 番目の路線の運賃，$h_i$ ($1 \le h_i \le H$) は路線の所要時間，$r_i$ ($1 \le r_i \le K$) は路線を管理している会社を表す．
ある2つの駅を結ぶ路線が2本以上存在することはない．
次の行で，D氏の最寄り駅 $S$ と，A氏のライブ会場の最寄り駅 $T$ が与えられる ($1 \le S, T \le N$)．
$S$ と $T$ は異なる値である．
次に，1Dayパスポートの情報が与えられる．
$P$ ($0 \le P \le 2^K - 1$) は，1Dayパスポートの種類数を表している．
続いて $P$ 行にわたって，1Dayパスポートの情報が入力される．
$l_j$ ($1 \le l_j \le K$) と $d_j$ ($1 \le d_j \le 10{,}000$) は，それぞれ $j$ 番目の1Dayパスポートに書かれている会社数とパスポートの料金を表す．
同じ行に，$j$ 番目のパスポートに書かれた $l_j$ 個の会社番号 $k_{j, 1}, k_{j, 2}, \ldots, k_{j, l_j}$ ($1 \le k_{j, 1} \lt k_{j, 2} \lt \cdots \lt k_{j, l_j} \le K$) が与えられる．
同じ会社の組み合わせからなる1Dayパスポートが複数入力されることはない．
入力の終わりは，$N=M=H=K=0$ の行によって表される．
このデータは処理を行ってはならない．
Output
各データセットに対して，計算結果を1行で出力せよ．
すなわち，D氏の最寄り駅からライブ会場の最寄り駅への経路が存在し $H$ 時間以内に到達できるのであれば，そのための最小の料金を，辿り着けないのであれば-1を出力せよ．
Sample Input
3 3 3 2
1 2 3 1 1
1 3 8 1 1
2 3 3 2 2
1 3
0
3 3 2 2
1 2 3 1 1
1 3 8 1 1
2 3 3 2 2
1 3
0
6 4 3 2
1 2 3 1 1
1 3 8 1 1
4 6 3 2 2
5 6 7 2 2
1 6
0
3 3 3 2
1 2 3 1 1
1 3 8 1 1
2 3 3 2 2
1 3
2
2 6 1 2
1 2 2
3 3 2 2
1 2 3 1 1
1 3 8 1 1
2 3 3 2 2
1 3
2
2 6 1 2
1 2 2
3 2 2 2
1 2 3 1 1
2 3 3 2 2
1 3
2
2 6 1 2
1 2 2
5 4 20 4
2 4 100 5 1
1 4 100 5 3
1 5 100 5 4
3 5 100 5 2
3 2
3
2 80 1 2
2 60 1 3
2 40 2 3
0 0 0 0
Output for Sample Input
6
8
-1
5
6
-1
200

Submitted solutions:

code_snippet: #include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
#ifdef _WIN32
#define __builtin_popcount __popcnt
#endif
// Time Complexity: O(3^P + 2^P * H * M log N)
int N, M, H, K, S, T, P, a, b, c, h, r;
int main() {
	while (cin >> N >> M >> H >> K, N) {
		vector<vector<vector<int> > > G(N);
		for (int i = 0; i < M; i++) {
			cin >> a >> b >> c >> h >> r; a--, b--, r--;
			G[a].push_back({ b, c, h, r });
			G[b].push_back({ a, c, h, r });
		}
		vector<int> cost(1 << K, 999999999); cost[0] = 0;
		cin >> S >> T >> P; S--, T--;
		for (int i = 0; i < P; i++) {
			cin >> a >> b;
			int bit = 0;
			for (int j = 0; j < a; j++) cin >> c, c--, bit += 1 << c;
			cost[bit] = b;
		}
		vector<pair<int, int> > v;
		for (int i = 0; i < 1 << K; i++) v.push_back(make_pair(__builtin_popcount(i), i));
		sort(v.begin(), v.end());
		for (int i = 0; i < v.size(); i++) {
			for (int j = 0; j < i; j++) {
				cost[i | j] = min(cost[i | j], cost[i] + cost[j]);
			}
		}
		int ret = 999999999;
		for (int i = 0; i < 1 << K; i++) {
			vector<vector<int> > dist(N, vector<int>(H + 1, 999999999)); dist[S][0] = 0;
			priority_queue<vector<int> > que; que.push({ 0, S, 0 });
			while (!que.empty()) {
				vector<int> u = que.top(); que.pop();
				for (int j = 0; j < G[u[1]].size(); j++) {
					int f = G[u[1]][j][0], d = u[2] + G[u[1]][j][2], c = dist[u[1]][u[2]];
					if (!(i & (1 << G[u[1]][j][3]))) c += G[u[1]][j][1];
					if (d <= H && dist[f][d] > c) {
						dist[f][d] = c;
						que.push({ -dist[f][d], f, d });
					}
				}
			}
			int res = 999999999;
			for (int j = 0; j <= H; j++) res = min(res, dist[T][j]);
			ret = min(ret, res + cost[i]);
		}
		cout << (ret != 999999999 ? ret : -1) << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 4430
memory_kb: 3684
final_rank: 15

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

bool solve() {
    int N, M, H, K;
    cin >> N >> M >> H >> K;
    if (N == 0) return false;
    // station, cost, time, company
    vector<vector<tuple<int, int, int, int>>> G(N);
    for (int u, v, c, t, r; M--; ) {
        cin >> u >> v >> c >> t >> r;
        u--, v--, r--;
        G[u].emplace_back(v, c, t, r);
        G[v].emplace_back(u, c, t, r);
    }
    int S, T;
    cin >> S >> T;
    S--, T--;
    const long long inf = 1LL << 60;
    vector<long long> fare(1 << K, inf);
    for (int bit = 0; bit < 1 << K; bit++) {
        vector<vector<long long>> D(N, vector<long long>(H + 1, inf));
        D[S][0] = 0;
        // cost, station, time
        using tpl = tuple<long long, int, int>;
        priority_queue<tpl, vector<tpl>, greater<tpl>> q;
        q.emplace(0, S, 0);
        while (q.size()) {
            auto [cur, u, t] = q.top();
            q.pop();
            if (D[u][t] < cur) continue;
            for (auto [v, c, w, r] : G[u]) {
                if (bit >> r & 1) c = 0;
                if (t + w <= H && D[v][t + w] > cur + c) {
                    D[v][t + w] = cur + c;
                    q.emplace(cur + c, v, t + w);
                }
            }
        }
        for (int h = 0; h <= H; h++) {
            fare[bit] = min(fare[bit], D[T][h]);
        }
        // cout << memo[bit] << " \n"[bit + 1 == 1 << K];
    }
    long long ans = inf;
    vector<long long> pas(1 << K, inf);
    pas[0] = 0;
    int P;
    cin >> P;
    while (P--) {
        int L, D;
        cin >> L >> D;
        int C = 0;
        while (L--) {
            int k;
            cin >> k;
            C ^= 1 << (k - 1);
        }
        for (int i = 0; i < 1 << K; i++) {
            pas[i | C] = min(pas[i | C], pas[i] + D);
        }
    }
    for (int i = 0; i < 1 << K; i++) {
        ans = min(ans, pas[i] + fare[i]);
    }
    if (ans == inf) ans = -1;
    cout << ans << '\n';
    return true;
}

int main() {
    while (solve()) {}
}
accuracy: 1
time_ms: 2080
memory_kb: 3712
final_rank: 10

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

using ll = long long;
#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define sz(x) (int)(x).size()
#define all(x) x.begin(), x.end()
typedef pair<int, int> pii;
typedef vector<int> vi;
template <class T>
inline bool chmin(T &a, T b) {
  return ((a > b) ? (a = b, 1) : (0));
}
template <class T>
inline bool chmax(T &a, T b) {
  return ((a < b) ? (a = b, 1) : (0));
}

int main() {
  while (solve());
  return 0;
}

bool solve() {
  int N,M,H,K;cin>>N>>M>>H>>K;
  if (N==0) return 0;
  using t4=tuple<int,int,int,int>;
  vector<vector<t4>>G(N);
  rep(i,0,M){
    int a,b,c,h,r;cin>>a>>b>>c>>h>>r;
    a--,b--,r--;
    G[a].emplace_back(b,c,h,r);
    G[b].emplace_back(a,c,h,r);
  }
  int S,T;cin>>S>>T;
  S--,T--;
  int P;cin>>P;
  vi l(P),d(P);
  vi k(P);
  rep(i,0,P){
    cin>>l[i]>>d[i];
    rep(j,0,l[i]){
      int x;cin>>x;
      x--;
      k[i]|=1<<x;
    }
  }

  const int inf = 1001001001;
  vi dp(1<<K,inf);
  dp[0]=0;
  {
    //bitdp
    rep(s,0,1<<K){
      if(dp[s]<inf)
      rep(i,0,P){
        int ns=s|k[i];
        dp[ns]=min(dp[ns],dp[s]+d[i]);
      }
    }
  }

  int ans = inf;
  rep(s,0,1<<K){//1daypassによる無料路線会社集合
    if(dp[s]==inf)continue;
    vector md(N,vi(H+1,inf));
    md[S][0]=dp[s];
    
    priority_queue<pair<int,pii>,vector<pair<int,pii>>,greater<pair<int,pii>>>q;
    q.emplace(0,pii(S,0));
    while(!q.empty()){
      auto [fir,sec]=q.top();q.pop();
      auto [v,h]=sec;
      for(auto [to,c,ah,r]:G[v]){
        int nh=h+ah;
        if(nh<=H){
          int cost=c;
          if((1<<r)&s)cost=0;
          if(chmin(md[to][nh],md[v][h]+cost)){
            q.emplace(md[to][nh],pii(to,nh));
          }
        }
      }
    }

    rep(h,0,H+1)chmin(ans,md[T][h]);
  }
  if(ans==inf)ans=-1;
  cout<<ans<<endl;
  return 1;
}
accuracy: 1
time_ms: 1650
memory_kb: 3712
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
#define rep(i, n) for (ll i = 0; i < (ll)(n); i++)
#define rrep(i,start,end) for (ll i = start;i >= (ll)(end);i--)
#define repn(i,end) for(ll i = 0; i <= (ll)(end); i++)
#define reps(i,start,end) for(ll i = start; i < (ll)(end); i++)
#define repsn(i,start,end) for(ll i = start; i <= (ll)(end); i++)
#define each(p,a) for(auto &p:a)
typedef vector<ll> vll;
typedef vector<pair<ll ,ll>> vpll;
typedef vector<vector<ll>> vvll;
typedef set<ll> sll;
typedef map<ll , ll> mpll;
typedef pair<ll ,ll> pll;
typedef tuple<ll , ll , ll> tpl3;
#define LL(...) ll __VA_ARGS__; input(__VA_ARGS__)
#define LD(...) ld __VA_ARGS__; input(__VA_ARGS__)
#define Str(...) string __VA_ARGS__; input(__VA_ARGS__)
#define Ch(...) char __VA_ARGS__; input(__VA_ARGS__)
#define all(a)  (a).begin(),(a).end()
#define UNIQUE(v) v.erase( unique(v.begin(), v.end()), v.end() );
#define sz(x) (ll)x.size()
// << std::fixed << std::setprecision(10)
const ll INF = 1LL << 60;
const ld EPS = 1e-9;
 
ll lceil(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b)+1;}else{return -((-a)/b);}}
ll lfloor(ll a,ll b){if(a%b==0){return a/b;}if(a>=0){return (a/b);}else{return -((-a)/b)-1;}}
inline ll positive_mod(ll a,ll m){return (a % m + m)%m;}
inline ll popcnt(ull a){ return __builtin_popcountll(a);}
//0indexed
inline ll topbit(ll a){assert(a != 0);return 63 - __builtin_clzll(a);}
inline ll smlbit(ll a){assert(a != 0);return __builtin_ctzll(a);}
template<class T> bool chmin(T& a, T b){if(a > b){a = b;return true;}return false;}
template<class T> bool chmax(T& a, T b){if(a < b){a = b;return true;}return false;}
template<typename T> std::istream &operator>>(std::istream&is,std::vector<T>&v){for(T &in:v){is>>in;}return is;}
template<typename T> std::ostream &operator<<(std::ostream&os,const std::vector<T>&v){for(auto it=std::begin(v);it!=std::end(v);){os<<*it<<((++it)!=std::end(v)?" ":"");}return os;}
template<typename T1, typename T2>std::ostream &operator<< (std::ostream &os, std::pair<T1,T2> p){os << "{" << p.first << "," << p.second << "}";return os;}
template<class... T>void input(T&... a){(cin >> ... >> a);}
void print(){cout << endl;}
template<class T, class... Ts>void print(const T& a, const Ts&... b){cout << a;((cout << ' ' << b), ...);cout << endl;}
template<class T> void pspace(const T& a){ cout << a << ' ';}
void perr(){cerr << endl;}
template<class T, class... Ts>void perr(const T& a, const Ts&... b){cerr << a;((cerr << ' ' << b), ...);cerr << endl;}
void yes(bool i = true){ return print(i?"yes":"no"); }
void Yes(bool i = true){ return print(i?"Yes":"No"); }
void YES(bool i = true){ return print(i?"YES":"NO"); }
template <class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v) e++;return v;}
template <class T> vector<T> operator++(vector<T> &v, signed) {auto res = v;for(auto &e : v) e++;return res;}
template <class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v) e--;return v;}
template <class T> vector<T> operator--(vector<T> &v, signed) {auto res = v;for(auto &e : v) e--;return res;}
//grid探索用
vector<ll> _ta = {0,0,1,-1,1,1,-1,-1};
vector<ll> _yo = {1,-1,0,0,1,-1,1,-1};
bool isin(ll now_i,ll now_j,ll h,ll w){return (0<=now_i && now_i < h && 0 <= now_j && now_j < w);}
  
ll lpow(ll x,ll n){ll ans = 1;while(n >0){if(n & 1)ans *= x;x *= x;n >>= 1;}return ans;}
ll Modlpow(ll x,ll n,ll m){ll ans = 1;ll a = x%m;while(n >0){if(n & 1){ans *= a;ans%= m;}a *= a;a %= m;n >>= 1;}return ans;} 
const ll MOD9 = 998244353LL;
const ll MOD10 = 1000000007LL;

// for AOJ or ICPC or etc..
template<class Tp>
bool zero (const Tp &x) {
    return x == 0;
}

template<class Tp, class... Args>
bool zero (const Tp &x, const Args& ...args) {
    return zero(x) and zero(args...);
}


using tpl4 = tuple<ll,ll,ll,ll>;
void solve(ll n,ll m,ll H,ll K){
  vector<vector<tpl4>> g(n);
  rep(i,m){
    LL(a,b,c,h,r);
    a--;b--;r--;
    g[a].emplace_back(b,c,h,r);
    g[b].emplace_back(a,c,h,r);
  }
  LL(s,t);
  s--;t--;
  LL(P);
  vll pascost(1 << K,INF);
  pascost[0] = 0;
  rep(i,P){
    LL(l,d);
    ll companies = 0;
    rep(j,l){
      LL(k);
      k--;
      companies += 1 << k;
    }
    rrep(j,(1<<K)-1,0){
      chmin(pascost[j|companies],pascost[j]+d);
    }
  }
  ll ans =INF;
  rep(pas,1 << K){//このパスを持っているときのを計算
    vvll dist(n,vll(H+1,INF));//最小コスト
    dist[s][0] = 0;
    priority_queue<tpl3,vector<tpl3>,greater<tpl3>> pq;
    pq.emplace(0,s,0);//コスト場所時間
    while(!pq.empty()){
      auto [nowcost,now,time] = pq.top();
      pq.pop();
      for(auto &[to,c,h,r]:g[now]){
        ll ncost = (pas >> r & 1)? 0:c;
        if(time+h<=H && dist[to][time+h] > nowcost+ncost){
          dist[to][time+h] = nowcost+ncost;
          pq.emplace(dist[to][time+h],to,time+h);
        }
      }
    }
    //tに行けるか
    repn(i,H){
      if(dist[t][i] < INF){
        chmin(ans,dist[t][i] + pascost[pas]);
      }
    }
  }
  if(ans >= INF){
    cout << -1 << endl;
  }else{
    cout << ans << endl;
  }


}

 
int main(){
  ios::sync_with_stdio(false);cin.tie(nullptr);
  while(true){
    LL(n,m,H,K);
    if(zero(n,m,H,K))break;
    solve(n,m,H,K);
  }
}
accuracy: 1
time_ms: 2220
memory_kb: 3840
final_rank: 11

code_snippet: // #ifndef ONLINE_JUDGE
// #define _GLIBCXX_DEBUG
// #endif
#include <bits/stdc++.h>
using namespace std;
#include <atcoder/all>
using namespace atcoder;
// #include <boost/rational.hpp>
// using namespace boost;
// using rat = rational<long long int>;
using mint = modint998244353;
// using mint = modint1000000007;
// using mint = mint;
using ll = long long;
using ld = long double;
using ull = uint64_t;
using pll = pair<ll, ll>;
using vll = vector<ll>;
using vvll = vector<vll>;
using vvvll = vector<vvll>;
using vpll = vector<pll>;
using vvpll = vector<vpll>;
using vm = vector<mint>;
using vvm = vector<vm>;
using vvvm = vector<vvm>;
using vstr = vector<string>;
#define v(T) vector<T>
#define vv(T) vector<vector<T>>
#define vvv(T) vector<vector<vector<T>>>
#define vvvv(T) vector<vector<vector<vector<T>>>>

istream &operator>>(istream &is, mint &a){ll tmp; is >> tmp; a = tmp; return is;}
ostream &operator<<(ostream &os, const mint &a){ os << a.val(); return os; }
string to_string(const __int128_t &a) { if (a == 0) return "0"; string s = ""; __int128_t num = a; bool is_negative = false; if (num < 0) { is_negative = true; num = -num; } while (num > 0) { s += '0' + (num % 10); num /= 10; } if (is_negative) s += '-'; reverse(s.begin(), s.end()); return s; }
istream &operator>>(istream &is, __int128_t &a){ string s; is >> s; a = 0; for(char c : s) { if(isdigit(c)) {a = a*10 + (c - '0'); }  } if(s[0]=='-'){ a *= -1; } return is; }
ostream &operator<<(ostream &os, const __int128_t &a){ os << to_string(a); return os; }
template<class T, class U> istream &operator>>(istream &is, pair<T, U> &p) { is >> p.first >> p.second; return is; }
template<class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) { os << p.first << " " << p.second; return os; }
template<class T> istream &operator>>(istream &is, vector<T> &vec){ for(T &e : vec){is >> e;} return is; }
template<class T> ostream &operator<<(ostream &os, const vector<T> &vec) { for(int i = 0; i < (int)vec.size(); i++) { os << vec[i] << (i + 1 != (int)vec.size() ? " " : ""); } return os; }

template <class... T> constexpr auto min (T... a) { return min(initializer_list<common_type_t<T...>>{a...}); }
template <class... T> constexpr auto max (T... a) { return max(initializer_list<common_type_t<T...>>{a...}); }
template<class T> using pqg = priority_queue<T, vector<T>, greater<T>>;
template<class T> T opmin(T x, T y) { return min(x, y); }
template<class T> T einf() { return numeric_limits<T>::max(); }
template<class T> T opmax(T x, T y) { return max(x, y); }
template<class T> T eminf() { return numeric_limits<T>::min(); }
template<class T> T opsum(T x, T y) { return x + y; }
template<class T> T ezero() { return (T)0; }
// #define maxseg(T) segtree<T, [](T x, T y){return max(x, y);}, [](){return (T)(-(1LL << 60));}>
// #define minseg(T) segtree<T, [](T x, T y){return min(x, y);}, [](){return (T)((1LL << 60));}>
// #define sumseg(T) segtree<T, [](T x, T y){return x + y;}, [](){return (T)(0);}>
template<class T> using minseg = segtree<T, opmin<T>, einf<T>>;
template<class T> using maxseg = segtree<T, opmax<T>, eminf<T>>;
template<class T> using sumseg = segtree<T, opsum<T>, ezero<T>>;
// template<class T> struct v : vector<T> { using vector<T> :: vector; };
// template<class T> struct vv : vector<v<T>> { using vector<v<T>> :: vector; };
// template<class T> struct vvv : vector<vv<T>> { using vector<vv<T>> :: vector; };
template<class T> inline bool chmin(T& a, T b) {if(a > b){a = b; return true;} else {return false;}};
template<class T> inline bool chmax(T& a, T b) {if(a < b){a = b; return true;} else {return false;}};
#define rep(i,n) for(ll i = 0; i < (ll)(n); i++)
#define repr(i,n) for(ll i = (ll)(n) - 1; i >= 0; i--)
#define REP(i, l, r) for(ll i = (ll)l; i <= (ll)(r); i++)
#define REPR(i, l, r) for(ll i = (ll)r; i >= (ll)(l); i--)
const ll inf = (1 << 30);
const ll INF = (1LL << 60);
const vector<pair<ll, ll>> DIJ = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
void out(){cout<<'\n';}
template<class T, class... Ts> void out(const T& a, const Ts&... b){ cout<<a; (cout<<... << (cout << ' ', b)); cout << '\n';}
void outf(){cout<<endl;}
template<class T, class... Ts> void outf(const T& a, const Ts&... b){ cout<<a; (cout<<... << (cout << ' ', b)); cout << endl;}
template<class T, class U> void outp(pair<T, U> a){ out((a).first, (a).second); }
template<class T, class U> void outpf(pair<T, U> a){ outf((a).first, (a).second); }
template<class T> void outv(T a){rep(i, (a).size()){ cout << (a)[i] << " "; } cout << endl;}
template<class T> void outvL(T a){rep(i, (a).size()){out((a)[i]);} cout << flush; }
// template<class T> void outvv(T a){rep(i, a.size()){ rep(j, a.at(i).size()){cout << a.at(i).at(j) << " "; } cout << endl; }}
// template<class T> void outvp(T a){rep(i, a.size()){ out2(a.at(i).first, a.at(i).second); }}
void setpre(int a){cout << fixed << setprecision(a);}
#define outN out("No")
#define outY out("Yes")
#define outYN(flag) out(flag ? "Yes" : "No")
#define dame(...) {outf(__VA_ARGS__);return 0;}

template<class T> void read(vector<T>& vec){ for(int i = 0; i < (int)vec.size(); i++) { cin >> vec[i]; } }
template<class... T> void read(T&... a){(cin >> ... >> a);}
#define readll(...) ll __VA_ARGS__; read(__VA_ARGS__)
#define readvll(a, n) vector<ll> a(n); read(a)
#define readvt(type, a, n) vector<type> a(n); read(a)
#define readvll2(a, b, n) vector<ll> a(n), b(n); for(int lopi = 0; lopi < (int)(n); lopi++) cin >> (a)[lopi] >> (b)[lopi]
#define readvll3(a, b, c, n) vector<ll> a(n), b(n), c(n); for(int lopi = 0; lopi < (int)(n); lopi++) cin >> (a)[lopi] >> (b)[lopi] >> (c)[lopi]
#define readstr(...) string __VA_ARGS__; read(__VA_ARGS__)
#define readundirG(G, N, M) G = vvll(N); rep(lopi, M) {ll a, b; cin >> a >> b; G[a-1].push_back(b-1); G[b-1].push_back(a-1);}
#define readdirG(G, N, M) G = vvll(N); rep(lopi, M) {ll a, b; cin >> a >> b; G[a-1].push_back(b-1);}
#define readundirwghG(G, N, M) G = vv(pll)(N); rep(lopi, M) {ll a, b, c; cin >> a >> b >> c; G[a-1].emplace_back(b-1,c); G[b-1].emplace_back(a-1, c);}
#define readdirwghG (G, N, M) G = vv(pll)(N); rep(lopi, M) {ll a, b, c; cin >> a >> b >> c; G[a-1].emplace_back(b-1, c);}

#define All(a) (a).begin(), (a).end()
template<class T> inline void sortr(T& a){ sort((a).rbegin(), (a).rend()); }
template<class T> inline vector<int> argsort(T V, bool rev = false){vector<int> res(V.size()); iota(res.begin(), res.end(), 0); sort(res.begin(), res.end(), [&](int x, int y){if(!rev){return V[x] < V[y];}else{return V[x] > V[y];}}); return res;}
template<class T, class U> inline void sort_by_idx(T& V, vector<U>& I){assert(V.size() == I.size()); T tmpv = V; for(int loopi = 0; loopi < (int)I.size(); loopi++){V[loopi] = tmpv[I.at(loopi)];}}
template<class T, class U> inline void sortp(vector<T>& v1, vector<U>& v2, bool rev1 = false, int rev2 = false){assert(v1.size() == v2.size()); vector<int> I(v1.size()); iota(I.begin(), I.end(), 0); sort(I.begin(), I.end(), [&](const int x, const int y){if(v1[x] != v1[y]){return (bool)(rev1 ^ (v1[x] < v1[y]));}else{if(v2[x]==v2[y]){return false;} return (bool)(rev2 ^ (v2[x] < v2[y]));}}); sort_by_idx(v1, I); sort_by_idx(v2, I);}
template<class T> T POW(T x, ll n) {T ret = 1; while(n > 0){if(n & 1) ret *= x; x *= x; n >>= 1;} return ret;}
ll powll(ll x, ll n){ll ret = 1; while(n > 0){if(n & 1) ret *= x; x *= x; n >>= 1;} return ret;}
inline ll divceil(ll x, ll y) { if(x >= 0) {return(x / y + (ll)(x % y != 0)); } else { return -((-x) / y); } }
inline ll divfloor(ll x, ll y) { if(x >= 0) { return x/y; } else { return -((-x)/y + (ll)((-x) % y != 0)); } }
inline bool inLR(ll x, ll L, ll R){ return (L <= x && x < R); }
inline bool inRect(ll pos_x, ll pos_y, ll rect_H, ll rect_W, ll rect_h = 0, ll rect_w = 0){ return (rect_h <= pos_x && pos_x < rect_H && rect_w <= pos_y && pos_y < rect_W); }

template<class T> vector<T> &operator++(vector<T> &v) {for(auto &e : v){e++;} return v;}
template<class T> vector<T> operator++(vector<T> &v, signed) {auto res=v; for(auto &e : v){e++;} return res;}
template<class T> vector<T> &operator--(vector<T> &v) {for(auto &e : v){e--;} return v;}
template<class T> vector<T> operator--(vector<T> &v, signed) {auto res=v; for(auto &e : v){e--;} return res;}
template<class T> vector<T> operator+(const vector<T> &x, const vector<T> &y) { assert(x.size() == y.size()); vector<T> ret(x.size()); for(int i = 0; i < (int)x.size(); i++) {ret[i] = x[i] + y[i];} return ret; }
template<class T> vector<T> operator-(const vector<T> &x, const vector<T> &y) { assert(x.size() == y.size()); vector<T> ret(x.size()); for(int i = 0; i < (int)x.size(); i++) {ret[i] = x[i] - y[i];} return ret; } 

template<class T, class U> pair<T, U> operator+(const pair<T, U> &x, const pair<T, U> &y) { return make_pair(x.first + y.first, x.second + y.second); }
template<class T, class U> pair<T, U> operator-(const pair<T, U> &x, const pair<T, U> &y) { return make_pair(x.first - y.first, x.second - y.second); }
template<class T, class U> void operator+=(pair<T, U> &x, pair<T, U> &y) { x = x + y; }
template<class T, class U> void operator-=(pair<T, U> &x, pair<T, U> &y) { x = x - y; }

template<class T> size_t HashCombine(const size_t seed,const T &v){ return seed^(std::hash<T>()(v)+0x9e3779b9+(seed<<6)+(seed>>2)); }
template<class T,class S> struct std::hash<std::pair<T,S>>{ size_t operator()(const std::pair<T,S> &keyval) const noexcept { return HashCombine(std::hash<T>()(keyval.first), keyval.second); } };
template<class T> struct std::hash<std::vector<T>>{ size_t operator()(const std::vector<T> &keyval) const noexcept { size_t s=0; for (auto&& v: keyval) s=HashCombine(s,v); return s; } };
template<int N> struct HashTupleCore{ template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ size_t s=HashTupleCore<N-1>()(keyval); return HashCombine(s,std::get<N-1>(keyval)); } };
template <> struct HashTupleCore<0>{ template<class Tuple> size_t operator()(const Tuple &keyval) const noexcept{ return 0; } };
template<class... Args> struct std::hash<std::tuple<Args...>>{ size_t operator()(const tuple<Args...> &keyval) const noexcept { return HashTupleCore<tuple_size<tuple<Args...>>::value>()(keyval); } };

struct edge
{
    ll to, c, h, r;
};

int main()
{
    std::cin.tie(nullptr), std::ios_base::sync_with_stdio(false);
    while(true)
    {
        readll(N, M, H, K);
        if(!N) break;
        vector<vector<edge>> G(N);
        rep(i, M)
        {
            readll(a, b, c, h, r);
            a--; b--; r--;
            G[a].emplace_back(b, c, h, r);
            G[b].emplace_back(a, c, h, r);
        }
        readll(s, t);
        s--; t--;

        readll(P);
        vll dpS(1LL << K, INF);
        dpS[0] = 0;
        rep(i, P)
        {
            readll(L, D);
            ll S = 0;
            vll ndp = dpS;
            rep(i, L)
            {
                readll(k);
                k--;
                S |= 1LL << k;
            }
            rep(bit, 1LL << K)
            {
                chmin(ndp[bit | S], dpS[bit] + D);
            }
            dpS.swap(ndp);
        }
        ll ans = INF;
        rep(S, 1LL << K)
        {
            vvll dp(N, vll(H + 1, INF));
            dp[s][0] = 0;
            pqg<pair<ll, pll>> pq;
            pq.emplace(0, pll{s, 0});
            while(!pq.empty())
            {
                auto [d, nh] = pq.top(); pq.pop();
                auto [n, hh] = nh;
                if(dp[n][hh] < d) continue;
                for(auto [e, c, h, r] : G[n])
                {
                    if(hh + h > H) continue;
                    ll nxt = dp[n][hh] + (((S >> r) & 1) ? 0 : c);
                    if(chmin(dp[e][hh + h], nxt))
                    {
                        pq.emplace(nxt, pll{e, hh+h});
                    }
                }
            }
            rep(h, H + 1) chmin(ans, dp[t][h] + dpS[S]);
        }
        if(ans == INF) out(-1);
        else out(ans);
    }
}
accuracy: 1
time_ms: 1820
memory_kb: 3968
final_rank: 7

code_snippet: # include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const double pi = acos(-1);
template<class T>constexpr T inf() { return ::std::numeric_limits<T>::max(); }
template<class T>constexpr T hinf() { return inf<T>() / 2; }
template <typename T_char>T_char TL(T_char cX) { return tolower(cX); }
template <typename T_char>T_char TU(T_char cX) { return toupper(cX); }
template<class T> bool chmin(T& a,T b) { if(a > b){a = b; return true;} return false; }
template<class T> bool chmax(T& a,T b) { if(a < b){a = b; return true;} return false; }
int popcnt(unsigned long long n) { int cnt = 0; for (int i = 0; i < 64; i++)if ((n >> i) & 1)cnt++; return cnt; }
int d_sum(ll n) { int ret = 0; while (n > 0) { ret += n % 10; n /= 10; }return ret; }
int d_cnt(ll n) { int ret = 0; while (n > 0) { ret++; n /= 10; }return ret; }
ll gcd(ll a, ll b) { if (b == 0)return a; return gcd(b, a%b); };
ll lcm(ll a, ll b) { ll g = gcd(a, b); return a / g*b; };
ll MOD(ll x, ll m){return (x%m+m)%m; }
ll FLOOR(ll x, ll m) {ll r = (x%m+m)%m; return (x-r)/m; }
template<class T> using dijk = priority_queue<T, vector<T>, greater<T>>;
# define all(qpqpq)           (qpqpq).begin(),(qpqpq).end()
# define UNIQUE(wpwpw)        (wpwpw).erase(unique(all((wpwpw))),(wpwpw).end())
# define LOWER(epepe)         transform(all((epepe)),(epepe).begin(),TL<char>)
# define UPPER(rprpr)         transform(all((rprpr)),(rprpr).begin(),TU<char>)
# define rep(i,upupu)         for(ll i = 0, i##_len = (upupu);(i) < (i##_len);(i)++)
# define reps(i,opopo)        for(ll i = 1, i##_len = (opopo);(i) <= (i##_len);(i)++)
# define len(x)                ((ll)(x).size())
# define bit(n)               (1LL << (n))
# define pb push_back
# define eb emplace_back
# define exists(c, e)         ((c).find(e) != (c).end())

struct INIT{
	INIT(){
		std::ios::sync_with_stdio(false);
		std::cin.tie(0);
		cout << fixed << setprecision(20);
	}
}INIT;

namespace mmrz {
	void solve();
}

int main(){
	mmrz::solve();
}
#define debug(...) (static_cast<void>(0))

using namespace mmrz;

using vll=vector<ll>;
using vvll = vector<vector<ll>>;
using ull = unsigned long long;
using lll = __int128;
#define per(i,n) for(ll i=n-1;i>=0;--i)
#define rep2(i,a,n) for (ll i=a;i<n;++i)
#define per2(i,a,n) for (ll i=a;i>=n;--i)

// [BEGIN] template の include

int SOLVE(){
	int n, m, H, k;
	cin >> n >> m >> H >> k;
	if(n == 0 && m == 0 && H == 0 && k == 0)return 1;
	
	// to cst time company
	vector<vector<tuple<int, int, int, int>>> g(n);
	while(m--){
		int a, b, c, h, r;
		cin >> a >> b >> c >> h >> r;
		a--, b--, r--;
		g[a].eb(b, c, h, r);
		g[b].eb(a, c, h, r);
	}
	int s, t;
	cin >> s >> t;
	s--, t--;
	
	vector<int> final_cst(bit(k), hinf<int>());
	rep(S, bit(k)){
		vector dis(n, vector(H+1, hinf<int>()));
		dis[s][0] = 0;
		dijk<tuple<int, int, int>> pq;
		pq.push(make_tuple(0, 0, s));
		while(not pq.empty()){
			auto [cst, cur_time, cur_v] = pq.top();
			pq.pop();
			for(auto [to, ec, et, company] : g[cur_v]){
				int edge_cst = (S >> company & 1 ? 0 : ec);
				if(cur_time+et > H)continue;
				if(chmin(dis[to][cur_time+et], dis[cur_v][cur_time]+edge_cst)){
					pq.push(make_tuple(dis[to][cur_time+et], cur_time+et, to));
				}
			}
		}
		rep(i, H+1)chmin(final_cst[S], dis[t][i]);
	}

	int p;
	cin >> p;
	vector<int> dp(bit(k), hinf<int>());
	dp[0] = 0;
	while(p--){
		int p_set = 0;
		int l, d;
		cin >> l >> d;
		while(l--){
			int c;
			cin >> c;
			c--;
			p_set |= bit(c);
		}
		auto ep = dp;
		rep(S, bit(k)){
			chmin(ep[S|p_set], dp[S]+d);
		}
		swap(dp, ep);
	}
	int ans = hinf<int>();
	rep(S, bit(k)){
		chmin(ans, final_cst[S]+dp[S]);
	}
	cout << (ans == hinf<int>() ? -1 : ans) << '\n';
	return 0;
}

void mmrz::solve(){
	while(!SOLVE());
}
accuracy: 1
time_ms: 1910
memory_kb: 3840
final_rank: 8

code_snippet: #include "bits/stdc++.h"
using namespace std;
using ll = long long;
using ld = long double;
using ull = unsigned long long;
#define rep(i, m, n) for (ll i = (ll)m; i < (ll)n; i++)
#define drep(i, m, n) for (ll i = m - 1; i >= n; i--)
#define Endl endl
#define all(a) a.begin(), a.end()
#define pr(i, j) make_pair(i, j)
#define isin(x, l, r) (l <= x && x < r)
#define chmin(a, b) a = min(a, b)
#define chmax(a, b) a = max(a, b)
#define srt(ar) sort(ar.begin(), ar.end())
#define rev(ar) reverse(ar.begin(), ar.end())
#define jge(f, s, t) cout << (f ? s : t) << endl
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")

#define printar(ar)             \
    do                          \
    {                           \
        for (auto dbg : ar)     \
        {                       \
            cout << dbg << " "; \
        }                       \
        cout << endl;           \
    } while (0)
const ll inf = 1e18;
const ld pi = 3.14159265358979;
const ld eps = 1e-9;
template <class T, ll n, ll idx = 0>
auto make_vec(const ll (&d)[n], const T &init) noexcept
{
    if constexpr (idx < n)
        return std::vector(d[idx], make_vec<T, n, idx + 1>(d, init));
    else
        return init;
}

template <class T, ll n>
auto make_vec(const ll (&d)[n]) noexcept
{
    return make_vec(d, T{});
}
//////////////// 以下を貼る ////////////////
template <class T>
size_t HashCombine(const size_t seed, const T &v)
{
    return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}
/* pair用 */
template <class T, class S>
struct std::hash<std::pair<T, S>>
{
    size_t operator()(const std::pair<T, S> &keyval) const noexcept
    {
        return HashCombine(std::hash<T>()(keyval.first), keyval.second);
    }
};
////////////////////////////////////////////
struct T
{
    ll to;
    ll cost;
    ll time;
    ll comp;
};
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    while (true)
    {
        ll n, m, h, K;
        cin >> n >> m >> h >> K;
        if (n == 0)
        {
            break;
        }
        vector<vector<T>> g(n);
        rep(i, 0, m)
        {
            ll a, b, c, x, y;
            cin >> a >> b >> c >> x >> y;
            a--;
            b--;
            y--;
            T X, Y;
            X.to = b;
            Y.to = a;
            X.cost = c;
            Y.cost = c;
            X.time = x;
            Y.time = x;
            X.comp = y;
            Y.comp = y;
            g[a].push_back(X);
            g[b].push_back(Y);
        }
        ll s, t;
        cin >> s >> t;
        s--;
        t--;
        ll p;
        cin >> p;
        vector<ll> d(p);
        vector<ll> pass(p);
        rep(i, 0, p)
        {
            ll l;
            cin >> l >> d[i];
            ll sub = 0;
            rep(j, 0, l)
            {
                ll x;
                cin >> x;
                x--;
                sub += (1LL << x);
            }
            pass[i] = sub;
        }
        vector<ll> dp(1LL << K, inf);
        dp[0] = 0;
        rep(i, 0, p)
        {
            drep(j, (1LL << K), 0)
            {
                chmin(dp[j | pass[i]], dp[j] + d[i]);
            }
        }
        ll ans = inf;
        rep(i, 0, (1LL << K))
        {
            if (dp[i] == inf)
            {
                continue;
            }
            ll sub = inf;
            auto dp2 = make_vec({h + 1, n}, inf);
            dp2[0][s] = 0;
            rep(j, 0, h + 1)
            {
                rep(k, 0, n)
                {
                    rep(l, 0, g[k].size())
                    {
                        ll to = g[k][l].to;
                        ll cost = g[k][l].cost;
                        ll time = g[k][l].time;
                        ll comp = g[k][l].comp;
                        if (j + time > h)
                        {
                            continue;
                        }
                        if ((i >> comp) & 1)
                        {
                            cost = 0;
                        }
                        chmin(dp2[j + time][to], dp2[j][k] + cost);
                    }
                }
            }
            rep(j, 0, h + 1)
            {
                chmin(sub, dp2[j][t]);
            }
            if (sub != inf)
            {
                chmin(ans, sub + dp[i]);
            }
        }
        if (ans == inf)
        {
            cout << -1 << endl;
        }
        else
        {
            cout << ans << endl;
        }
    }
}
accuracy: 1
time_ms: 290
memory_kb: 3712
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define all(a) a.begin(),a.end()
#define reps(i, a, n) for (int i = (a); i < (int)(n); i++)
#define rep(i, n) reps(i, 0, n)
#define rreps(i, a, n) for (int i = (a); i > (int)(n); i--)
const long long mod = 1000000007;
const long long INF = 1e18;
ll myceil(ll a, ll b) {return (a+b-1)/b;}


int n,m,hh,k;

void solve() {
    vector<int> a(m),b(m),c(m),h(m),r(m);

    rep(i,m) cin >> a[i] >> b[i] >> c[i] >> h[i] >> r[i];

    vector<vector<pair<int,int>>> g(n,vector<pair<int,int>> (0));

    rep(i,m) {
        a[i]--;
        b[i]--;
        r[i]--;

        g[a[i]].push_back({b[i],i});
        g[b[i]].push_back({a[i],i});
    }

    int s,t;
    cin >> s >> t;
    s--; t--;


    vector<ll> pass(1<<k,INF);
    pass[0] = 0;
    int p;
    cin >> p;


    int l,d,kk;
    rep(i,p) {
        cin >> l >> d;
        int ps = 0;
        rep(j,l) {
            cin >> kk;
            ps += 1<<(kk-1);
        }
        pass[ps] = d;
        for (int ncmb = ps; ncmb; ncmb = (ncmb - 1) & ps) {
            pass[ncmb] = min(pass[ncmb],pass[ps]);
        }
    }


    rep(cmb,1<<k) {
        for (int ncmb = cmb; ncmb; ncmb = (ncmb - 1) & cmb) {
            int hos = cmb-ncmb;
            pass[cmb] = min(pass[cmb],pass[ncmb]+pass[hos]);
        }
    }






    ll ans = 1e9;
    rep(msk,1<<k) {
        if (pass[msk] == INF) continue;

        vector<vector<int>> dijk(hh+1,vector<int> (n,1e9));
        
        dijk[0][s] = 0;

        priority_queue<pair<int,pair<int,int>>,vector<pair<int,pair<int,int>>>,greater<>> pq;  
        pq.push({0,{0,s}});

        // fare,time,dest

        while (!pq.empty()) {
            auto pp = pq.top();
            pq.pop();
            int fr = pp.first;
            int tm = pp.second.first;
            int dest = pp.second.second;

            if (dijk[tm][dest] != fr) continue;

            for (auto x : g[dest]) {
                int to = x.first;
                int nm = x.second;

                if (msk & 1<<r[nm]) {
                    if (tm+h[nm] <= hh) {
                        if (dijk[tm+h[nm]][to] > fr) {
                            dijk[tm+h[nm]][to] = fr;
                            pq.push({fr,{tm+h[nm],to}});
                        }
                    }
                }
                else {
                    if (tm+h[nm] <= hh) {
                        if (dijk[tm+h[nm]][to] > fr+c[nm]) {
                            dijk[tm+h[nm]][to] = fr+c[nm];
                            pq.push({fr+c[nm],{tm+h[nm],to}});
                        }
                    }
                }
            }
        }


        rep(i,hh+1) {
            ans = min(ans,dijk[i][t]+pass[msk]);
        }
    }

    if (ans != 1e9) {
        cout << ans << endl;
    }
    else {
        cout << -1 << endl;
    }
    return;
}


int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    while (cin >> n >> m >> hh >> k && n != 0) {
        solve();
    }


	return 0;
}
accuracy: 1
time_ms: 1840
memory_kb: 3840
final_rank: 6

code_snippet: // (⁠◕⁠ᴗ⁠◕⁠✿⁠)

// #pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#define rep(i, n) for (ll i = 0; i < (n); i++)
#define srep(i, s, n) for (ll i = s; i < (n); i++)
#define len(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
using namespace std;
template<typename T> using vc = vector<T>;
template<typename T> using vv = vc<vc<T>>;
template<typename T> using vvv = vv<vc<T>>;
using vi = vc<int>;using vvi = vv<int>; using vvvi = vv<vi>;
using ll = long long;using vl = vc<ll>;using vvl = vv<ll>; using vvvl = vv<vl>;
using ld = long double; using vld = vc<ld>; using vvld = vc<vld>; using vvvld = vc<vvld>;
using uint = unsigned int;
using ull = unsigned long long;
const ld pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
// const ll mod = 1000000007;
const ll mod = 998244353;
inline bool inside(ll y, ll x, ll H, ll W) {return 0 <= (y) and (y) < (H) and 0 <= (x) and (x) < (W); }

#define debug(var)  do{std::cout << #var << " : \n";view(var);}while(0)
template<typename T> void view(T e){cout << e << endl;}
template<typename T> void view(const vc<T>& v){for(const auto& e : v){ cout << e << " "; } cout << endl;}
template<typename T> void view(const vv<T>& vv){ for(const auto& v : vv){ view(v); } }

int N, M, H, K;

void solve(){
    vv<tuple<int, int, int>> g(N * (H + 1));
    rep(i, M){
        int a, b, c, h, r; cin >> a >> b >> c >> h >> r; a--; b--; r--;
        rep(j, H) if (j + h <= H){
            g[j * N + a].push_back({c, r, (j + h) * N + b});
            g[j * N + b].push_back({c, r, (j + h) * N + a});
        }
    }
    int s, t; cin >> s >> t; s--; t--;
    int P; cin >> P;
    vi cost(1 << K, inf);
    cost[0] = 0;
    rep(i, P){
        int l, d; cin >> l >> d;
        int cmb = 0;
        rep(j, l){
            int k; cin >> k; k--;
            cmb += (1 << k);
        }
        cost[cmb] = min(cost[cmb], d);
    }
    rep(cmb, 1 << K) for (int ncmb = cmb; ncmb; ncmb = (ncmb - 1) & cmb){
        int scmb = cmb ^ ncmb;
        for (int tcmb = ncmb;; tcmb = (tcmb - 1) & ncmb){
            cost[cmb] = min(cost[cmb], cost[ncmb] + cost[scmb | tcmb]);
            if (tcmb == 0) break;
        }
    }
    int ans = inf;
    rep(cmb, 1 << K) if (cost[cmb] < inf){
        priority_queue<pair<int, int>, vc<pair<int, int>>, greater<>> pq;
        vi dist(N * (H + 1), inf);
        pq.push({cost[cmb], s});
        dist[s] = cost[cmb];
        while (!pq.empty()){
            auto [c, v] = pq.top(); pq.pop();
            if (dist[v] < c) continue;
            for (auto [nc, r, u] : g[v]){
                if (cmb >> r & 1){
                    if (dist[u] > dist[v]){
                        dist[u] = dist[v];
                        pq.push({dist[u], u});
                    }
                }else{
                    if (dist[u] > dist[v] + nc){
                        dist[u] = dist[v] + nc;
                        pq.push({dist[u], u});
                    }
                }
            }
        }
        rep(j, H + 1) ans = min(ans, dist[j * N + t]);
    }
    if (ans == inf) ans = -1;
    cout << ans << endl;
}

int main(){
    while (true){
        cin >> N >> M >> H >> K;
        if (N == 0) break;
        solve();
    }
}
accuracy: 1
time_ms: 1540
memory_kb: 3784
final_rank: 3

code_snippet: #include <bits/stdc++.h>
    using namespace std;
    
    template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
    template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
    #define rep(i,n) for (int i = 0; i < (n); ++i)

    typedef long long ll;
    typedef unsigned long long ull;
    using P=pair<ll,ll>;
    using T=tuple<int,int,int>;
    const int INF=1001001001;
    const ll INFL=1e18;
    const int mod=998244353;
	
	struct edge{
		int to,c,h,r;
		edge(int to,int c,int h,int r):to(to),c(c),h(h),r(r){}
	};
		
	int dijkstra(int s,int t,int S,int H,vector<vector<edge>>& G){
		int n=G.size();
		vector<vector<int>>dist(n,vector<int>(30,INF));
		dist[s][0]=0;
		priority_queue<T,vector<T>,greater<T>>q;
		q.push(make_tuple(0,0,s));
		int ans=INF;
		while(!q.empty()){
			auto[d,h,v]=q.top();q.pop();
			if(v==t){
				chmin(ans,d);
			}
			if(d>dist[v][h]){continue;}
			for(auto e:G[v]){
				int add=d;
				if(~S>>e.r&1)add+=e.c;
			  	if(h+e.h<=H&&chmin(dist[e.to][h+e.h],add)){
					q.push(make_tuple(dist[e.to][h+e.h],h+e.h,e.to));
			  	}
			}
		}
		return ans;
	}
	
    bool solve(){
		int n,m,H,k;
		cin>>n>>m>>H>>k;
		if(!n&&!m&&!H&&!k)return false;
		
		vector<vector<edge>>G(n);
		rep(i,m){
			int a,b,c,h,r;
			cin>>a>>b>>c>>h>>r;
			a--;b--;r--;
			G[a].emplace_back(b,c,h,r);
			G[b].emplace_back(a,c,h,r);
		}

		int s,t;
		cin>>s>>t;
		s--;t--;
		vector<int>pass(1<<k,INF);
		pass[0]=0;
		int p;
		cin>>p;
		rep(i,p){
			int l,d;
			cin>>l>>d;
			int V=0;
			rep(j,l){
				int v;
				cin>>v;
				v--;
				V|=(1<<v);
			}
			rep(S,1<<k){
				int nS=(S|V);
				chmin(pass[nS],pass[S]+d);
			}
		}
		int ans=INF;
		rep(S,1<<k){
			int dist=dijkstra(s,t,S,H,G);
			chmin(ans,dist+pass[S]);
		}
		if(ans==INF)ans=-1;
		cout<<ans<<endl;
		return true;
    }

    int main(){
        ios_base::sync_with_stdio(false);
        cin.tie(NULL);

		while(1){
			if(!solve())break;
		}
		
        return 0;
    }
accuracy: 1
time_ms: 1870
memory_kb: 3712
final_rank: 5

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rrep(i, a, b) for (int i = (int)(b)-1; i >= (int)(a); i--)
#define ALL(v) (v).begin(), (v).end()
#define UNIQUE(v) sort(ALL(v)), (v).erase(unique(ALL(v)), (v).end())
#define SZ(v) (int)v.size()
#define MIN(v) *min_element(ALL(v))
#define MAX(v) *max_element(ALL(v))
#define LB(v, x) int(lower_bound(ALL(v), (x)) - (v).begin())
#define UB(v, x) int(upper_bound(ALL(v), (x)) - (v).begin())

using uint = unsigned int;
using ll = long long int;
using ull = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;
const int inf = 0x3fffffff;
const ll INF = 0x1fffffffffffffff;

template <typename T> inline bool chmax(T &a, T b) {
    if (a < b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T> inline bool chmin(T &a, T b) {
    if (a > b) {
        a = b;
        return 1;
    }
    return 0;
}
template <typename T, typename U> T ceil(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? (x + y - 1) / y : x / y);
}
template <typename T, typename U> T floor(T x, U y) {
    assert(y != 0);
    if (y < 0)
        x = -x, y = -y;
    return (x > 0 ? x / y : (x - y + 1) / y);
}
template <typename T> int popcnt(T x) {
    return __builtin_popcountll(x);
}
template <typename T> int topbit(T x) {
    return (x == 0 ? -1 : 63 - __builtin_clzll(x));
}
template <typename T> int lowbit(T x) {
    return (x == 0 ? -1 : __builtin_ctzll(x));
}

template <class T, class U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
    os << "P(" << p.first << ", " << p.second << ")";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const vector<T> &vec) {
    os << "{";
    for (int i = 0; i < vec.size(); i++) {
        os << vec[i] << (i + 1 == vec.size() ? "" : ", ");
    }
    os << "}";
    return os;
}
template <typename T, typename U>
ostream &operator<<(ostream &os, const map<T, U> &map_var) {
    os << "{";
    for (auto itr = map_var.begin(); itr != map_var.end(); itr++) {
        os << "(" << itr->first << ", " << itr->second << ")";
        itr++;
        if (itr != map_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
template <typename T> ostream &operator<<(ostream &os, const set<T> &set_var) {
    os << "{";
    for (auto itr = set_var.begin(); itr != set_var.end(); itr++) {
        os << *itr;
        ++itr;
        if (itr != set_var.end())
            os << ", ";
        itr--;
    }
    os << "}";
    return os;
}
#ifdef LOCAL
#define show(...) _show(0, #__VA_ARGS__, __VA_ARGS__)
#else
#define show(...) true
#endif
template <typename T> void _show(int i, T name) {
    cerr << '\n';
}
template <typename T1, typename T2, typename... T3>
void _show(int i, const T1 &a, const T2 &b, const T3 &...c) {
    for (; a[i] != ',' && a[i] != '\0'; i++)
        cerr << a[i];
    cerr << ":" << b << " ";
    _show(i + 1, a, c...);
}

#include <unistd.h>

namespace fastio {
static constexpr uint32_t SZ = 1 << 17;
char ibuf[SZ];
char obuf[SZ];
char out[100];
// pointer of ibuf, obuf


uint32_t pil = 0, pir = 0, por = 0;

struct Pre {
    char num[10000][4];
    constexpr Pre() : num() {
        for (int i = 0; i < 10000; i++) {
            int n = i;
            for (int j = 3; j >= 0; j--) {
                num[i][j] = n % 10 | '0';
                n /= 10;
            }
        }
    }
} constexpr pre;

inline void load() {
    memmove(ibuf, ibuf + pil, pir - pil);
    pir = pir - pil + fread(ibuf + pir - pil, 1, SZ - pir + pil, stdin);
    pil = 0;
    if (pir < SZ)
        ibuf[pir++] = '\n';
}

inline void flush() {
    fwrite(obuf, 1, por, stdout);
    por = 0;
}

void rd(char &c) {
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
}

void rd(string &x) {
    x.clear();
    char c;
    do {
        if (pil + 1 > pir)
            load();
        c = ibuf[pil++];
    } while (isspace(c));
    do {
        x += c;
        if (pil == pir)
            load();
        c = ibuf[pil++];
    } while (!isspace(c));
}

template <typename T> void rd_real(T &x) {
    string s;
    rd(s);
    x = stod(s);
}

template <typename T> void rd_integer(T &x) {
    if (pil + 100 > pir)
        load();
    char c;
    do
        c = ibuf[pil++];
    while (c < '-');
    bool minus = 0;
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (c == '-') {
            minus = 1, c = ibuf[pil++];
        }
    }
    x = 0;
    while ('0' <= c) {
        x = x * 10 + (c & 15), c = ibuf[pil++];
    }
    if constexpr (is_signed<T>::value || is_same_v<T, i128>) {
        if (minus)
            x = -x;
    }
}

void rd(int &x) {
    rd_integer(x);
}
void rd(ll &x) {
    rd_integer(x);
}
void rd(i128 &x) {
    rd_integer(x);
}
void rd(uint &x) {
    rd_integer(x);
}
void rd(ull &x) {
    rd_integer(x);
}
void rd(u128 &x) {
    rd_integer(x);
}
void rd(double &x) {
    rd_real(x);
}
void rd(long double &x) {
    rd_real(x);
}

template <class T, class U> void rd(pair<T, U> &p) {
    return rd(p.first), rd(p.second);
}
template <size_t N = 0, typename T> void rd_tuple(T &t) {
    if constexpr (N < std::tuple_size<T>::value) {
        auto &x = std::get<N>(t);
        rd(x);
        rd_tuple<N + 1>(t);
    }
}
template <class... T> void rd(tuple<T...> &tpl) {
    rd_tuple(tpl);
}

template <size_t N = 0, typename T> void rd(array<T, N> &x) {
    for (auto &d : x)
        rd(d);
}
template <class T> void rd(vector<T> &x) {
    for (auto &d : x)
        rd(d);
}

void read() {}
template <class H, class... T> void read(H &h, T &...t) {
    rd(h), read(t...);
}

void wt(const char c) {
    if (por == SZ)
        flush();
    obuf[por++] = c;
}
void wt(const string s) {
    for (char c : s)
        wt(c);
}
void wt(const char *s) {
    size_t len = strlen(s);
    for (size_t i = 0; i < len; i++)
        wt(s[i]);
}

template <typename T> void wt_integer(T x) {
    if (por > SZ - 100)
        flush();
    if (x < 0) {
        obuf[por++] = '-', x = -x;
    }
    int outi;
    for (outi = 96; x >= 10000; outi -= 4) {
        memcpy(out + outi, pre.num[x % 10000], 4);
        x /= 10000;
    }
    if (x >= 1000) {
        memcpy(obuf + por, pre.num[x], 4);
        por += 4;
    } else if (x >= 100) {
        memcpy(obuf + por, pre.num[x] + 1, 3);
        por += 3;
    } else if (x >= 10) {
        int q = (x * 103) >> 10;
        obuf[por] = q | '0';
        obuf[por + 1] = (x - q * 10) | '0';
        por += 2;
    } else
        obuf[por++] = x | '0';
    memcpy(obuf + por, out + outi + 4, 96 - outi);
    por += 96 - outi;
}

template <typename T> void wt_real(T x) {
    ostringstream oss;
    oss << fixed << setprecision(15) << double(x);
    string s = oss.str();
    wt(s);
}

void wt(int x) {
    wt_integer(x);
}
void wt(ll x) {
    wt_integer(x);
}
void wt(i128 x) {
    wt_integer(x);
}
void wt(uint x) {
    wt_integer(x);
}
void wt(ull x) {
    wt_integer(x);
}
void wt(u128 x) {
    wt_integer(x);
}
void wt(double x) {
    wt_real(x);
}
void wt(long double x) {
    wt_real(x);
}

template <class T, class U> void wt(const pair<T, U> val) {
    wt(val.first);
    wt(' ');
    wt(val.second);
}
template <size_t N = 0, typename T> void wt_tuple(const T t) {
    if constexpr (N < std::tuple_size<T>::value) {
        if constexpr (N > 0) {
            wt(' ');
        }
        const auto x = std::get<N>(t);
        wt(x);
        wt_tuple<N + 1>(t);
    }
}
template <class... T> void wt(tuple<T...> tpl) {
    wt_tuple(tpl);
}
template <class T, size_t S> void wt(const array<T, S> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}
template <class T> void wt(const vector<T> val) {
    auto n = val.size();
    for (size_t i = 0; i < n; i++) {
        if (i)
            wt(' ');
        wt(val[i]);
    }
}

void print() {
    wt('\n');
}
template <class Head, class... Tail> void print(Head &&head, Tail &&...tail) {
    wt(head);
    if (sizeof...(Tail))
        wt(' ');
    print(forward<Tail>(tail)...);
}
void __attribute__((destructor)) _d() {
    flush();
}
} // namespace fastio


using fastio::flush;
using fastio::print;
using fastio::read;

inline void first(bool i = true) {
    print(i ? "first" : "second");
}
inline void Alice(bool i = true) {
    print(i ? "Alice" : "Bob");
}
inline void Takahashi(bool i = true) {
    print(i ? "Takahashi" : "Aoki");
}
inline void yes(bool i = true) {
    print(i ? "yes" : "no");
}
inline void Yes(bool i = true) {
    print(i ? "Yes" : "No");
}
inline void No() {
    print("No");
}
inline void YES(bool i = true) {
    print(i ? "YES" : "NO");
}
inline void NO() {
    print("NO");
}
inline void Yay(bool i = true) {
    print(i ? "Yay!" : ":(");
}
inline void Possible(bool i = true) {
    print(i ? "Possible" : "Impossible");
}
inline void POSSIBLE(bool i = true) {
    print(i ? "POSSIBLE" : "IMPOSSIBLE");
}

/**
 * @brief Fast IO
 */

template <unsigned mod = 1000000007> struct fp {
    unsigned v;
    static constexpr int get_mod() {
        return mod;
    }
    constexpr unsigned inv() const {
        assert(v != 0);
        int x = v, y = mod, p = 1, q = 0, t = 0, tmp = 0;
        while (y > 0) {
            t = x / y;
            x -= t * y, p -= t * q;
            tmp = x, x = y, y = tmp;
            tmp = p, p = q, q = tmp;
        }
        if (p < 0)
            p += mod;
        return p;
    }
    constexpr fp(ll x = 0) : v(x >= 0 ? x % mod : (mod - (-x) % mod) % mod) {}
    fp operator-() const {
        return fp() - *this;
    }
    fp pow(ull t) {
        fp res = 1, b = *this;
        while (t) {
            if (t & 1)
                res *= b;
            b *= b;
            t >>= 1;
        }
        return res;
    }
    fp &operator+=(const fp &x) {
        if ((v += x.v) >= mod)
            v -= mod;
        return *this;
    }
    fp &operator-=(const fp &x) {
        if ((v += mod - x.v) >= mod)
            v -= mod;
        return *this;
    }
    fp &operator*=(const fp &x) {
        v = ull(v) * x.v % mod;
        return *this;
    }
    fp &operator/=(const fp &x) {
        v = ull(v) * x.inv() % mod;
        return *this;
    }
    fp operator+(const fp &x) const {
        return fp(*this) += x;
    }
    fp operator-(const fp &x) const {
        return fp(*this) -= x;
    }
    fp operator*(const fp &x) const {
        return fp(*this) *= x;
    }
    fp operator/(const fp &x) const {
        return fp(*this) /= x;
    }
    bool operator==(const fp &x) const {
        return v == x.v;
    }
    bool operator!=(const fp &x) const {
        return v != x.v;
    }
    friend istream &operator>>(istream &is, fp &x) {
        return is >> x.v;
    }
    friend ostream &operator<<(ostream &os, const fp &x) {
        return os << x.v;
    }
};

template <unsigned mod> void rd(fp<mod> &x) {
    fastio::rd(x.v);
}
template <unsigned mod> void wt(fp<mod> x) {
    fastio::wt(x.v);
}

template <typename T> T Inv(ll n) {
    static const int md = T::get_mod();
    static vector<T> buf({0, 1});
    assert(n > 0);
    n %= md;
    while (SZ(buf) <= n) {
        int k = SZ(buf), q = (md + k - 1) / k;
        buf.push_back(buf[k * q - md] * q);
    }
    return buf[n];
}

template <typename T> T Fact(ll n, bool inv = 0) {
    static const int md = T::get_mod();
    static vector<T> buf({1, 1}), ibuf({1, 1});
    assert(n >= 0 and n < md);
    while (SZ(buf) <= n) {
        buf.push_back(buf.back() * SZ(buf));
        ibuf.push_back(ibuf.back() * Inv<T>(SZ(ibuf)));
    }
    return inv ? ibuf[n] : buf[n];
}

template <typename T> T nPr(int n, int r, bool inv = 0) {
    if (n < 0 || n < r || r < 0)
        return 0;
    return Fact<T>(n, inv) * Fact<T>(n - r, inv ^ 1);
}
template <typename T> T nCr(int n, int r, bool inv = 0) {
    if (n < 0 || n < r || r < 0)
        return 0;
    return Fact<T>(n, inv) * Fact<T>(r, inv ^ 1) * Fact<T>(n - r, inv ^ 1);
}
template <typename T> T nHr(int n, int r, bool inv = 0) {
    return nCr<T>(n + r - 1, r, inv);
}

/**
 * @brief Modint
 */

struct Edge {
    int To;
    ll C;
    int H;
    int R;
};

struct Node {
    ll C;
    int N;
    int R;
    int H;
};

auto f = [](const Node& A, const Node& B){
        if (A.C > B.C) return true;
        else return false;
    };

int main() {
while(1) {
    int N, M, H, K, S, T;
    cin >> N >> M >> H >> K;
    if (N == 0) return 0;
    vector<vector<Edge>> G(N);
    rep(i,0,M) {
        int S, T, H, R;
        ll C;
        cin >> S >> T >> C >> H >> R;
        S--, T--, R--;
        G[S].push_back({T,C,H,R});
        G[T].push_back({S,C,H,R});
    }
    cin >> S >> T;
    S--, T--;
    int P;
    cin >> P;
    vector<ll> Pass(1<<K,INF);
    Pass[0] = 0;
    rep(i,0,P) {
        int L;
        ll D;
        cin >> L >> D;
        int B = 0;
        rep(j,0,L) {
            int K;
            cin >> K;
            K--;
            B += (1<<K);
        }
        Pass[B] = D;
    }
    rep(i,0,1<<K) {
        rep(j,0,1<<K) {
            chmin(Pass[i|j], Pass[i]+Pass[j]);
        }
    }
    vector DP(N, vector(1<<K, vector<ll>(H+1,INF)));
    priority_queue<Node, vector<Node>, decltype(f)> PQ(f);
    rep(i,0,1<<K) {
        if (Pass[i] < INF) {
            DP[S][i][0] = Pass[i];
            PQ.push({Pass[i],S,i,0});
        }
    }
    while(!PQ.empty()) {
        Node P = PQ.top();
        PQ.pop();
        if (P.C > DP[P.N][P.R][P.H]) continue;
        for (Edge E : G[P.N]) {
            if (P.H + E.H > H) continue;
            if (chmin(DP[E.To][P.R][P.H+E.H], P.C+E.C)) {
                PQ.push({P.C+E.C,E.To,P.R,P.H+E.H});
            }
            if ((P.R & (1<<E.R)) == (1<<E.R)) {
                if (chmin(DP[E.To][P.R][P.H+E.H], P.C)) {
                    PQ.push({P.C,E.To,P.R,P.H+E.H});
                }
            }
        }
    }
    ll ANS = INF;
    rep(i,0,1<<K) {
        rep(j,0,H+1) {
            chmin(ANS, DP[T][i][j]);
        }
    }
    if (ANS == INF) cout << -1 << endl;
    else cout << ANS << endl;
}
}
accuracy: 1
time_ms: 3080
memory_kb: 20012
final_rank: 20

code_snippet: #include<bits/stdc++.h>
using namespace std;
#define rep(i,n) for (long long i=0;i<n;i++)
#define loop(i,m,n) for(long long i=m;i<=n;i++)
#define range(value,range) for(const auto &value : range)
#define ll long long
#define vl vector<long long>
#define vvl vector<vector<long long>>
#define vdbg(a) rep(ii,a.size()){cout<<a[ii]<<" ";}cout<<endl;
#define vvdbg(a) rep(ii,a.size()){rep(jj,a[ii].size()){cout<<a[ii][jj]<<" ";}cout<<endl;}
#define inf 4000000000000000000LL
#define mod 998244353

struct Node {
    ll to,from,cost,h;
};

ll solve() {
    ll n,m,h,k;
    cin >> n >> m >> h >> k;
    if(n==0)return 1;
    vl a(m),b(m),c(m),hh(m),r(m);
    rep(i,m) {
        cin >> a[i] >> b[i] >> c[i] >> hh[i] >> r[i];
        --a[i],--b[i],--r[i];
    }

    ll s,t,p;
    cin >> s >> t >> p;
    s--,t--;

    vvl dp(p+1,vl(1<<k,inf));
    dp[0][0]=0;
    rep(i,p) {
        ll l,d;
        cin >> l >> d;
        rep(j,1<<k)dp[i+1][j]=dp[i][j];
        ll bit=0;
        rep(j,l){
            ll kk;
            cin>>kk,kk--;
            bit+=(1<<kk);
        }
        rep(j,1<<k){
            dp[i+1][(j|bit)]=min(dp[i+1][(j|bit)],dp[i][j]+d);
        }
    }
    ll ans=inf;
    rep(z,1<<k){
        if(dp[p][z]==inf)continue;
        vector<vector<Node>> G(n);
        rep(i,m) {
            if((z&(1<<r[i]))==0){
                G[a[i]].push_back({b[i],a[i],c[i],hh[i]});
                G[b[i]].push_back({a[i],b[i],c[i],hh[i]});
            }else{
                G[a[i]].push_back({b[i],a[i],0,hh[i]});
                G[b[i]].push_back({a[i],b[i],0,hh[i]});
            }
        }
        //入れるのはコスト
        vvl dj(h+1,vl(n,inf));
        dj[0][s]=0;

        rep(i,h){
            rep(j,n){
                if(dj[i][j]==inf)continue;
                rep(l,G[j].size()){
                    if(i+G[j][l].h>h)continue;
                    dj[i+G[j][l].h][G[j][l].to]=min(dj[i+G[j][l].h][G[j][l].to],dj[i][j]+G[j][l].cost);
                }
            }
        }
        ll tmp=inf;
        loop(i,1,h){
            tmp=min(dj[i][t],tmp);
        }
        tmp+=dp[p][z];
        ans=min(ans,tmp);
    }
    if(ans==inf)cout<<-1<<endl;
    else cout<<ans<<endl;

    return 0;
}
int main(){
	while(1){
		if(solve()==1)break;
	}
	return 0;
}
accuracy: 1
time_ms: 490
memory_kb: 4064
final_rank: 2

code_snippet: #include<bits/stdc++.h>

using namespace std;
using ll = long long;
using Tpl4 = tuple<ll, ll, ll, ll>;
using Tpl3 = tuple<ll, ll, ll>;
template<class T> using min_heap = priority_queue<T, vector<T>, greater<T>>;
const ll INF = 1e9;
const ll LINF = 1e18;

int main(){
    while(true){
        int N, M, H, K; cin >> N >> M >> H >> K;
        if(N == 0) break;

        vector<vector<Tpl4>> G(N);
        for(int i = 0; i < M; i++){
            int a, b, c, h, r; cin >> a >> b >> c >> h >> r;
            a--, b--, r--;
            G[a].emplace_back(make_tuple(b, c, h, r));
            G[b].emplace_back(make_tuple(a, c, h, r));
        }

        int S, T, P; cin >> S >> T >> P;
        S--, T--;
        vector<ll> dp1(1 << K, LINF);
        dp1[0] = 0;
        for(int i = 0; i < P; i++){
            int l, d; cin >> l >> d;
            int bt = 0;
            for(int j = 0; j < l; j++){
                int kk; cin >> kk;
                bt |= (1 << (kk - 1));
            }
            dp1[bt] = d;
        }

        int Kb = (1 << K);
        for(int i = 0; i < Kb; i++){
            for(int j = 0; j < Kb; j++){
                for(int k = 0; k < Kb; k++){
                    if((j | k) == i) dp1[i] = min(dp1[i], dp1[j] + dp1[k]);
                }
            }
        }

        auto dijkstra = [&](auto bt) -> ll {
            vector<vector<ll>> dist(N, vector<ll>(H + 1, LINF));
            dist[S][0] = 0;
            min_heap<Tpl3> heap;
            heap.push(make_tuple(0, S, 0));
            while(!heap.empty()){
                auto [cst, u, h] = heap.top();
                heap.pop();
                if(cst > dist[u][h]) continue;
                for(auto [v, c, ho, r] : G[u]){
                    if(h + ho > H) continue;
                    if(bt & (1 << r)){
                        if(dist[v][h + ho] > dist[u][h]){
                            dist[v][h + ho] = dist[u][h];
                            heap.push(make_tuple(dist[v][h + ho], v, h + ho));
                        }
                    }
                    else{
                        if(dist[v][h + ho] > dist[u][h] + c){
                            dist[v][h + ho] = dist[u][h] + c;
                            heap.push(make_tuple(dist[v][h + ho], v, h + ho));
                        }
                    }
                }                
            }
            
            ll res = LINF;
            for(int i = 0; i <= H; i++) res = min(res, dist[T][i]);
            return res;
        };

        ll ans = LINF;
        for(int i = 0; i < Kb; i++){
            ans = min(ans, dp1[i] + dijkstra(i));
        }

        if(ans < LINF) cout << ans << endl;
        else cout << -1 << endl;
    }
}
accuracy: 1
time_ms: 2940
memory_kb: 3644
final_rank: 13

code_snippet: #include<bits/stdc++.h>

using namespace std;
using ll = long long;
using Tpl4 = tuple<ll, ll, ll, ll>;
using Tpl3 = tuple<ll, ll, ll>;
template<class T> using min_heap = priority_queue<T, vector<T>, greater<T>>;
const ll INF = 1e9;
const ll LINF = 1e18;

int main(){
    while(true){
        int N, M, H, K; cin >> N >> M >> H >> K;
        if(N == 0) break;

        vector<vector<Tpl4>> G(N);
        for(int i = 0; i < M; i++){
            int a, b, c, h, r; cin >> a >> b >> c >> h >> r;
            a--, b--, r--;
            G[a].emplace_back(make_tuple(b, c, h, r));
            G[b].emplace_back(make_tuple(a, c, h, r));
        }

        int S, T, P; cin >> S >> T >> P;
        S--, T--;
        vector<ll> dp1(1 << K, LINF);
        dp1[0] = 0;
        for(int i = 0; i < P; i++){
            int l, d; cin >> l >> d;
            int bt = 0;
            for(int j = 0; j < l; j++){
                int kk; cin >> kk;
                bt |= (1 << (kk - 1));
            }
            dp1[bt] = d;
        }

        int Kb = (1 << K);
        for(int i = 0; i < Kb; i++){
            for(int j = 0; j < Kb; j++){
                for(int k = 0; k < Kb; k++){
                    if((j | k) == i) dp1[i] = min(dp1[i], dp1[j] + dp1[k]);
                }
            }
        }

        auto dijkstra = [&](auto bt) -> ll {
            vector<vector<ll>> dist(N, vector<ll>(H + 1, LINF));
            dist[S][0] = 0;
            min_heap<Tpl3> heap;
            heap.push(make_tuple(0, S, 0));
            while(!heap.empty()){
                auto [cst, u, h] = heap.top();
                heap.pop();
                if(cst > dist[u][h]) continue;
                for(auto [v, c, ho, r] : G[u]){
                    if(h + ho > H) continue;
                    if(bt & (1 << r)){
                        if(dist[v][h + ho] > dist[u][h]){
                            dist[v][h + ho] = dist[u][h];
                            heap.push(make_tuple(dist[v][h + ho], v, h + ho));
                        }
                    }
                    else{
                        if(dist[v][h + ho] > dist[u][h] + c){
                            dist[v][h + ho] = dist[u][h] + c;
                            heap.push(make_tuple(dist[v][h + ho], v, h + ho));
                        }
                    }
                }                
            }
            
            ll res = LINF;
            for(int i = 0; i <= H; i++) res = min(res, dist[T][i]);
            return res;
        };

        ll ans = LINF;
        for(int i = 0; i < Kb; i++){
            ans = min(ans, dp1[i] + dijkstra(i));
        }

        if(ans < LINF) cout << ans << endl;
        else cout << -1 << endl;
    }
}
accuracy: 1
time_ms: 2940
memory_kb: 3536
final_rank: 12

code_snippet: #include <bits/stdc++.h>

struct Edge {
    Edge(int f, int t, int c, int h, int ty): from(f), to(t), cost(c), hour(h), type(ty) {}
    int from;
    int to;
    int cost;
    int hour;
    int type;
};

int solve() {
    int n, m, h, k;
    std::cin >> n >> m >> h >> k;
    if (n == 0) return 1;
    std::vector graph(n, std::vector<Edge>());
    for (int i = 0; i < m; i++) {
        int a, b, c, h, r;
        std::cin >> a >> b >> c >> h >> r;
        a--; b--; r--;
        graph[a].emplace_back(a, b, c, h, r);
        graph[b].emplace_back(b, a, c, h, r);
    }
    int start, goal;
    std::cin >> start >> goal;
    start--;
    goal--;
    int p;
    std::cin >> p;
    const int INF = 1e9;
    std::vector<int> dp(1 << k, INF);
    dp[0] = 0;
    for (int i = 0; i < p; i++) {
        int l, d;
        std::cin >> l >> d;
        int set = 0;
        for (int j = 0; j < l; j++) {
            int k;
            std::cin >> k;
            k--;
            set |= 1 << k;
        }
        dp[set] = d;
    }

    for (int state = 0; state < (1 << k); state++) {
        for (int mask = 0; mask < (1 << k); mask++) {
            dp[state | mask] = std::min(dp[state | mask], dp[state] + dp[mask]);
        }
    }

    int ans = INF;
    for (int state = 0; state < (1 << k); state++) {
        using P = std::tuple<int, int, int>;
        std::priority_queue<P, std::vector<P>, std::greater<P>> que;
        std::vector dist(h + 1, std::vector<int>(n, INF));
        dist[0][start] = 0;
        que.emplace(dist[0][start], 0, start);
        while (!que.empty()) {
            auto [d, i, j] = que.top();
            que.pop();
            if (dist[i][j] < d) continue;
            for (auto e: graph[j]) {
                int next_dist = dist[i][j];
                int next_hour = i + e.hour;
                if (next_hour > h) continue;
                if (state & (1 << e.type)) {
                    next_dist += 0;
                } else {
                    next_dist += e.cost;
                }
                if (dist[next_hour][e.to] > next_dist) {
                    dist[next_hour][e.to] = next_dist;
                    que.emplace(dist[next_hour][e.to], next_hour, e.to);
                }
            } 
        }
        for (int j = 0; j <= h; j++) {
            ans = std::min(ans, dist[j][goal] + dp[state]);
        }
    }

    if (ans == INF) {
        std::cout << -1 << '\n';
    } else {
        std::cout << ans << '\n';
    }

    return 0;
}

int main() {
    while (!solve());
}
accuracy: 1
time_ms: 2130
memory_kb: 3552
final_rank: 9

code_snippet: #include <bits/stdc++.h>

bool solve() {
    int N, M, H, K;
    std::cin >> N >> M >> H >> K;
    if (N == 0) return false;
    std::vector<std::tuple<int, int, int, int, int>> E(M);
    for (auto& [a, b, c, h, r] : E) {
        std::cin >> a >> b >> c >> h >> r;
        a--; b--; r--;
    }
    int S, T;
    std::cin >> S >> T;
    S--; T--;
    const int INF{(int)2e9};
    std::vector<long long> pass((1 << K), INF);
    pass[0] = 0;
    int P;
    std::cin >> P;
    for (int i{} ; i < P ; i++) {
        int l, d;
        std::cin >> l >> d;
        int set{};
        for (int j{} ; j < l ; j++) {
            int k;
            std::cin >> k;
            k--;
            assert(0 <= k and k < K);
            set |= (1 << k);
        }
        pass.at(set) = std::min(pass[set], (long long)d);
    }
    for (int bit{} ; bit < (1 << K) ; bit++) {
        for (int bit2{} ; bit2 <= bit ; bit2++) {
            pass[bit | bit2] = std::min(pass[bit | bit2], pass[bit] + pass[bit2]);
        }
    }
    const long long INVALID{(long long)1e18};
    long long ans{INVALID};
    for (int bit{} ; bit < (1 << K) ; bit++) {
        if (pass[bit] == INF) continue;
        std::vector<std::vector<std::pair<int, int>>> g(25 * N);
        auto check{[&](int v) -> bool {
            return 0 <= v and v < 25 * N;
        }};
        auto encode{[&](int t, int v) -> int {
            int res{t * N + v};
            if (!check(res)){
                std::cout << t << ' ' << v << " failed" << std::endl;
                assert(false);
            }
            return res;
        }};
        for (auto [a, b, c, h, r] : E) {
            int cost{(bit & (1 << r)) ? 0 : c};
            for (int i{} ; i + h <= 24 ; i++) {
                g[encode(i, a)].emplace_back(encode(i + h, b), cost);
                g[encode(i, b)].emplace_back(encode(i + h, a), cost);
            }
        }
        for (int i{} ; i + 1 <= 24 ; i++) {
            for (int j{} ; j < N ; j++) {
                g[encode(i, j)].emplace_back(encode(i + 1, j), 0);
            }
        }
        using qt = std::pair<long long, int>;
        std::vector<long long> dist(25 * N, INVALID); 
        dist[encode(0, S)] = 0;
        std::priority_queue<qt, std::vector<qt>, std::greater<qt>> que;
        que.emplace(dist[encode(0, S)], encode(0, S));
        while (que.size()) {
            auto [d, v]{que.top()};
            que.pop();
            if (dist.at(v) < d) continue;
            for (auto [x, w] : g[v]) {
                if (dist[x] > d + w) {
                    dist[x] = d + w;
                    que.emplace(dist[x], x);
                }
            }
        }
        long long val{INVALID};
        for (int i{} ; i <= H ; i++) {
            val = std::min(val, dist[encode(i, T)]);
        }
        val += pass[bit];
        ans = std::min(ans, val);
    }
    if (ans == INVALID) {
        std::cout << -1 << '\n';
    }
    else {
        std::cout << ans << '\n';
    }
    return true;
}

int main() {
    std::cin.tie(nullptr)->sync_with_stdio(false);
    while (solve()) ;
}
accuracy: 1
time_ms: 6250
memory_kb: 3784
final_rank: 17

code_snippet: #include <bits/stdc++.h>

bool solve() {
    int N, M, H, K; std::cin >> N >> M >> H >> K;
    if (N == 0) return false;
    using edge = std::tuple<int, int, int, int>;
    std::vector<std::vector<edge>> g(N);
    for (int _{} ; _ < M ; _++) {
        int a, b, c, h, r; std::cin >> a >> b >> c >> h >> r;
        a--; b--;
        r--;
        g[a].emplace_back(b, c, h, r);
        g[b].emplace_back(a, c, h, r);
    }
    int S, T; std::cin >> S >> T;
    S--; T--;
    const int INF{(int)1e9};
    std::vector<int> pass(1 << K, INF);
    pass[0] = 0;
    int P; std::cin >> P;
    for (int _{} ; _ < P ; _++) {
        int l, d; std::cin >> l >> d;
        int cur{};
        for (int i{} ; i < l ; i++) {
            int k; std::cin >> k;
            k--;
            cur |= (1 << k);
        }
        assert(pass[cur] == INF);
        pass[cur] = d;
    }
    // for (auto x : pass) std::cout << x << ' ';
    // std::cout << std::endl;
    for (int bit{} ; bit < (1 << K) ; bit++) {
        if (pass[bit] == INF) continue;
        for (int msk{} ; msk < (1 << K) ; msk++) {
            pass[bit | msk] = std::min(pass[bit | msk], pass[bit] + pass[msk]);
        }
    }
    // for (auto x : pass) std::cout << x << ' ';
    // std::cout << std::endl;
    int ans{INF};
    for (int bit{} ; bit < (1 << K) ; bit++) {
        if (pass[bit] == INF) continue;
        auto f{[&](int v, int time) -> int {
            return v * (H + 1) + time;
        }};
        std::vector<std::vector<std::pair<int, int>>> graph(N * (H + 1));
        for (int i{} ; i < N ; i++) {
            for (auto [x, c, h, r] : g[i]) {
                for (int j{} ; j <= H ; j++) {
                    if (j + h > H) break;
                    graph[f(i, j)].emplace_back(f(x, j + h), (bit & (1 << r)) ? 0 : c);
                }
            }
        }
        std::vector<int> deg(N * (H + 1));
        for (int i{} ; i < N ; i++) {
            for (int j{} ; j <= H ; j++) {
                for (auto [x, _] : graph[f(i, j)]) {
                    deg[x]++;
                }
            }
        }
        std::queue<int> que;
        for (int i{} ; i < N * (H + 1) ; i++) {
            if (deg[i] == 0) que.emplace(i);
        }
        std::vector<int> dist(N * (H + 1), INF);
        dist[f(S, 0)] = pass[bit];
        while (que.size()) {
            auto v{que.front()};
            que.pop();
            for (auto [x, cost] : graph[v]) {
                dist[x] = std::min(dist[x], dist[v] + cost);
                deg[x]--;
                if (deg[x] == 0) que.push(x);
            }
        }
        int val{INF};
        for (int i{} ; i <= H ; i++) {
            val = std::min(val, dist[f(T, i)]);
        }
        ans = std::min(ans, val);
    }
    if (ans == INF) {
        std::cout << -1 << '\n';
    }
    else {
        std::cout << ans << '\n';
    }
    return true;
}

int main() {
    while (solve()) ;
}
accuracy: 1
time_ms: 3440
memory_kb: 3576
final_rank: 14

code_snippet: #line 2 "cp-library/src/cp-template.hpp"
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull  = unsigned long long;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
template < class T > bool chmin(T& a, T b) { if(a > b) { a = b; return true; } return false; }
template < class T > bool chmax(T& a, T b) { if(a < b) { a = b; return true; } return false; }
template < class T, class U > T ceil (T x, U y) { return (x > 0 ? (x + y - 1) / y :           x / y); }
template < class T, class U > T floor(T x, U y) { return (x > 0 ?           x / y : (x - y + 1) / y); }
int popcnt(i32 x) { return __builtin_popcount(x); }
int popcnt(u32 x) { return __builtin_popcount(x); }
int popcnt(i64 x) { return __builtin_popcountll(x); }
int popcnt(u64 x) { return __builtin_popcountll(x); }

#line 2 "cp-library/src/utility/rep_itr.hpp"
template < class T > struct itr_rep {
    T i, d;
    constexpr itr_rep(const T i) noexcept : i(i), d(1) {}
    constexpr itr_rep(const T i, const T d) noexcept : i(i), d(d) {}
    void operator++() noexcept { i += d; }
    constexpr int operator*() const noexcept { return i; }
    constexpr bool operator!=(const itr_rep x) const noexcept { return d > 0 ? i < x.i : i > x.i; }
};

template < class T > struct rep {
    const itr_rep< T > s, t;
    constexpr rep(const T t) noexcept : s(0), t(t) {}
    constexpr rep(const T s, const T t) noexcept : s(s), t(t) {}
    constexpr rep(const T s, const T t, const T d) noexcept : s(s, d), t(t, d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};

template < class T > struct revrep {
    const itr_rep < T > s, t;
    constexpr revrep(const T t) noexcept : s(t - 1, -1), t(-1, -1) {}
    constexpr revrep(const T s, const T t) noexcept : s(t - 1, -1), t(s - 1, -1) {}
    constexpr revrep(const T s, const T t, const T d) noexcept : s(t - 1, -d), t(s - 1, -d) {}
    constexpr auto begin() const noexcept { return s; }
    constexpr auto end  () const noexcept { return t; }
};
#line 3 "cp-library/src/utility/io.hpp"

/* 128bit integer */
istream& operator>>(istream& is, i128& x) {
    std::string s; is >> s;
    int pm = (s[0] == '-');
    x = 0;
    for(int i : rep(pm, int(s.size()))) x = x * 10 + (s[i] - '0');
    if(pm) x *= -1;
    return is;
}
ostream& operator<<(ostream& os, const i128& x) {
    if(x == 0) return os << '0';
    i128 y = x;
    if(y < 0) { os << '-'; y *= -1; }
    std::vector<int> ny;
    while(y > 0) { ny.push_back(y % 10); y /= 10; }
    for(int i : revrep(ny.size())) os << ny[i];
    return os;
}

template < class S, class T > istream& operator>>(istream& is,       std::pair< S, T >& x) { is >> x.first        >> x.second; return is; }
template < class S, class T > ostream& operator<<(ostream& os, const std::pair< S, T >& x) { os << x.first << " " << x.second; return os; }

namespace scanner {
    struct sca {
        template < class T > operator T() {
            T s; std::cin >> s; return s;
        }
    };
    struct vec {
        int n;
        vec(int n) : n(n) {}
        template < class T > operator std::vector< T >() {
            std::vector< T > v(n);
            for(T& x : v) std::cin >> x;
            return v;
        }
    };
    struct mat {
        int h, w;
        mat(int h, int w) : h(h), w(w) {}
        template < class T > operator std::vector< std::vector< T > >() {
            std::vector m(h, std::vector< T >(w));
            for(std::vector< T >& v : m) for(T& x : v) std::cin >> x;
            return m;
        }
    };
    struct speedup {
        speedup() {
            std::cin.tie(0);
            std::ios::sync_with_stdio(0);
        }
    } speedup_instance;
}
scanner::sca in() { return scanner::sca(); }
scanner::vec in(int n) { return scanner::vec(n); }
scanner::mat in(int h, int w) { return scanner::mat(h, w); }

namespace printer {
    void precision(int d) { std::cout << std::fixed << std::setprecision(d); }
    void flush() { std::cout.flush(); }
}

template < class T >
ostream& operator<<(ostream& os, const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) { os << a[i]; if(i != n - 1) os << ' '; }
    return os;
}

int print() { std::cout << '\n'; return 0; }
template < class head, class... tail > int print(head&& h, tail&&... t) {
    std::cout << h; if(sizeof...(tail)) std::cout << ' ';
    return print(std::forward<tail>(t)...);
}
template < class T > int print_n(const std::vector< T > a) {
    int n = a.size();
    for(int i : rep(n)) std::cout << a[i] << "\n";
    return 0;
}


#line 2 "cp-library/src/utility/key_val.hpp"

template < class K, class V >
struct key_val {
    K key; V val;
    key_val() {}
    key_val(K key, V val) : key(key), val(val) {}
    template < std::size_t Index >
    std::tuple_element_t< Index, key_val >& get() {
        if constexpr (Index == 0) return key;
        if constexpr (Index == 1) return val;
    }
};

namespace std {

template < class K, class V > struct tuple_size < key_val< K, V > > : integral_constant< size_t, 2 > {};
template < class K, class V > struct tuple_element < 0, key_val< K, V > > { using type = K; };
template < class K, class V > struct tuple_element < 1, key_val< K, V > > { using type = V; };

}
#line 2 "cp-library/src/utility/vec_op.hpp"
template < class T > key_val< int, T > max_of(const vector< T >& a) {
    int i = std::max_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class T > key_val< int, T > min_of(const vector< T >& a) {
    int i = std::min_element(a.begin(), a.end()) - a.begin();
    return {i, a[i]};
}
template < class S, class T > S sum_of(const vector< T >& a) {
    S sum = 0;
    for(const T x : a) sum += x;
    return sum;
}
template < class S, class T > vector< S > freq_of(const vector< T >& a, T L, T R) {
    vector< S > res(R - L, S(0));
    for(const T x : a) res[x - L] += 1;
    return res;
}
template < class S, class T > struct prefix_sum {
    vector< S > s;
    prefix_sum(const vector< T >& a) : s(a) {
        s.insert(s.begin(), S(0));
        for(int i : rep(a.size())) s[i + 1] += s[i];
    }
    // [L, R)
    S sum(int L, int R) { return s[R] - s[L]; }
};
#line 3 "cp-library/src/utility/heap.hpp"

template < class T > using heap_min = std::priority_queue< T, std::vector< T >, std::greater< T > >;
template < class T > using heap_max = std::priority_queue< T, std::vector< T >, std::less< T > >;

#line 27 "cp-library/src/cp-template.hpp"

#line 1 "cp-library/src/algorithm/bin_search.hpp"
template < class T, class F >
T bin_search(T ok, T ng, F f) {
    while(abs(ng - ok) > 1) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}

template < class T, class F >
T bin_search_real(T ok, T ng, F f, int step = 80) {
    while(step--) {
        T mid = (ok + ng) / 2;
        (f(mid) ? ok : ng) = mid;
    }
    return ok;
}
#line 2 "cp-library/src/algorithm/argsort.hpp"

template < class T > std::vector< int > argsort(const std::vector< T > &a) {
    std::vector< int > ids((int)a.size());
    std::iota(ids.begin(), ids.end(), 0);
    std::sort(ids.begin(), ids.end(), [&](int i, int j) {
        return a[i] < a[j] || (a[i] == a[j] && i < j);
    });
    return ids;
}
#line 1 "macro.hpp"
namespace macro {

using size_type = int;
template < class container > void  sort(container& a) { std::sort(std:: begin(a), std:: end(a)); }
template < class container > void rsort(container& a) { std::sort(std::rbegin(a), std::rend(a)); }
template < class container > void reverse(container& a) { std::reverse(std::begin(a), std::end(a)); }
template < class container > void unique(container& a) {
    std::sort(std::begin(a), std::end(a));
    a.erase(std::unique(std::begin(a), std::end(a)), std::end(a));
}
template < class container > container  sorted(const container& a) { container b = a;  sort(b); return std::move(b); }
template < class container > container rsorted(const container& a) { container b = a; rsort(b); return std::move(b); }
template < class container, class compare > void sort(container& a, const compare& cmp) { std::sort(std::begin(a), std::end(a), cmp); }
template < class container, class compare > container sorted(const container& a, const compare& cmp) { container b = a; sort(b, cmp); return std::move(b); }
template < class container, class value > size_type lower_bound(const container& a, const value& x) { return std::lower_bound(std::begin(a), std::end(a), x) - std::begin(a); }
template < class container, class value > size_type upper_bound(const container& a, const value& x) { return std::upper_bound(std::begin(a), std::end(a), x) - std::begin(a); }

const std::vector<std::pair<size_type, size_type>> dir4 = { {+1,  0}, {-1,  0}, { 0, +1}, { 0, -1} };
const std::vector<std::pair<size_type, size_type>> dir8 = { {-1, -1}, {-1,  0}, {-1, +1}, { 0, -1}, { 0, +1}, {+1, -1}, {+1,  0}, {+1, +1} };

#ifdef _DEBUG
#define debug(x) std::cout << "[" << __LINE__ << "] " << #x << ": " << x << std::endl
#else
#define debug(x)
#endif

template < class container > void concat(container& a, const container& b) {
    a.insert(std::end(a), std::begin(b), std::end(b));
}
std::vector<size_type> iota(const size_type n) {
    std::vector<size_type> I(n);
    std::iota(std::begin(I), std::end(I), 0);
    return I;
}
template < class container > std::vector<size_type> sort_idx(const container& a) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return a[i] < a[j] or (a[i] == a[j] and i < j); });
    return I;
}
template < class container, class compare > std::vector<size_type> sort_idx(const container& a, const compare& cmp) {
    const size_type n = a.size();
    std::vector<size_type> I = iota(n);
    std::sort(std::begin(I), std::end(I), [&](size_type i, size_type j) { return cmp(a[i], a[j]) or (a[i] == a[j] and i < j); });
    return std::move(I);
}

struct grid {
    using size_type = int;
    size_type H, W;
    grid(const size_type H, const size_type W) : H(H), W(W) {}
    bool contains(const size_type i, const size_type j) {
        return 0 <= i and i < H and 0 <= j and j < W;
    }
};

using f64 = long double;

} // namespace macro

using namespace macro;
#line 1 "cp-library/src/graph/shortest_path.hpp"
// g <- pair < v , cost > 
template < class T >
vector< T > dijkstra(vector<vector<pair<int, T>>> &graph, int s) {
    T INF = numeric_limits< T >::max();
    vector<T> dist(graph.size(), INF);
    priority_queue<pair<T,int>, vector<pair<T,int>>, greater<pair<T,int>>> q;
    q.push({dist[s] = T(0), s});
    while(!q.empty()){
        auto [uc, ui] = q.top(); q.pop();
        if(uc != dist[ui]) continue;
        for(auto [vi, vc] : graph[ui]) if(dist[vi] > uc + vc) 
            q.push({dist[vi] = uc + vc, vi});
    }
    return dist;
}

// g <- pair < v , cost > 
template < class T >
vector< T > dijkstra(vector<vector<pair<int, T>>> &graph, vector<int> &starts) {
    T INF = numeric_limits< T >::max();
    vector<T> dist(graph.size(), INF);
    priority_queue<pair<T,int>, vector<pair<T,int>>, greater<pair<T,int>>> q;
    for(int s : starts) q.push({dist[s] = T(0), s});
    while(!q.empty()){
        auto [uc, ui] = q.top(); q.pop();
        if(uc != dist[ui]) continue;
        for(auto [vi, vc] : graph[ui]) if(dist[vi] > uc + vc) 
            q.push({dist[vi] = uc + vc, vi});
    }
    return dist;
}

// g <- pair < v , cost > 
template < class T >
pair< T, vector<int> > shortest_path(vector<vector<pair<int, T>>> &graph, int s, int t) {
    T INF = numeric_limits< T >::max();
    vector<T> dist(graph.size(), INF);
    vector<int> prev(graph.size(), -1);
    priority_queue<pair<T,int>, vector<pair<T,int>>, greater<pair<T,int>>> q;
    q.push({dist[s] = T(0), s});
    while(!q.empty()){
        auto [uc, ui] = q.top(); q.pop();
        if(uc != dist[ui]) continue;
        for(auto [vi, vc] : graph[ui]) if(dist[vi] > uc + vc) 
            q.push({dist[vi] = uc + vc, vi}), prev[vi] = ui;
    }

    vector<int> path;
    if(dist[t] != INF) {
        for(int v = t; v != -1; v = prev[v]) path.push_back(v);
        reverse(path.begin(), path.end());
    }
    return {dist[t], path};
}
#line 4 "A.cpp"

int solve(int N, int M, int H, int K) {
    vector<tuple<int,int,int,int,int>> E(M);
    for(auto &[a, b, c, h, r] : E) a = in(), b = in(), c = in(), h = in(), r = in(), a--, b--, r--;
    int S = in(), T = in(); S--, T--;

    vector<int> cost(1 << K, 1e9);
    cost[0] = 0;
    int P = in();
    for(int _ : rep(P)) {
        int l = in(), d = in();
        int set = 0;
        for(int l_ : rep(l)) {
            int k = in(); k--;
            set += (1 << k);
        }
        vector<int> next = cost;
        for(int now : rep(1 << K)) chmin(next[now | set], cost[now] + d);
        cost = move(next);
    }

    int ans = 1e9;
    for(int set : rep(1 << K)) if(cost[set] < 1e9) {
        vector<vector<pair<int,int>>> G(N * (H + 1));
        auto hash = [&](int v, int h) { return v * (H + 1) + h; };
        for(auto [a, b, c, h, r] : E) {
            for(int time = 0; time + h <= H; time++) {
                G[hash(a, time)].push_back({hash(b, time + h), set & (1 << r) ? 0 : c});
                G[hash(b, time)].push_back({hash(a, time + h), set & (1 << r) ? 0 : c});
            }
        }
        vector<int> dist = dijkstra(G, hash(S, 0));
        for(int time = 0; time <= H; time++) if(dist[hash(T, time)] < 1e9)
            chmin(ans, cost[set] + dist[hash(T, time)]);
    }
    return ans < 1e9 ? ans : -1;
}

int main() {
    while(true) {
        int N = in(), M = in(), H = in(), K = in();
        if(make_tuple(N, M, H, K) == make_tuple(0, 0, 0, 0)) return 0;
        print(solve(N, M, H, K));
    }
}
accuracy: 1
time_ms: 4780
memory_kb: 3748
final_rank: 16

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
#define rep(i, a, b) for(ll i = a; i < b; ++i)
#define rrep(i, a, b) for(ll i = a; i >= b; --i)
constexpr ll inf = 4e18;
int main(void) {
    cin.tie(0);
    ios::sync_with_stdio(0);
    while(true) {
        int N, M, H, K;
        cin >> N >> M >> H >> K;
        if(N == 0 and M == 0 and H == 0 and K == 0) break;
        H++;
        vector<int> a(M), b(M), c(M), h(M), r(M);
        rep(i, 0, M) {
            cin >> a[i] >> b[i] >> c[i] >> h[i] >> r[i];
            a[i]--;
            b[i]--;
            r[i]--;
        }
        int S, T;
        cin >> S >> T;
        S--;
        T--;
        int p;
        cin >> p;
        vector<int> l(p), d(p);
        vector<vector<int>> k(p);
        rep(i, 0, p) {
            cin >> l[i] >> d[i];
            k[i].resize(l[i]);
            rep(j, 0, l[i]) {
                cin >> k[i][j];
                k[i][j]--;
            }
        }
        vector<vector<int>> dp(p + 1, vector<int>(1 << K, 1e9));
        dp[0][0] = 0;
        rep(i, 1, p + 1) {
            rep(j, 0, 1 << K) {
                dp[i][j] = dp[i - 1][j];
                int mask = 0;
                rep(i1, 0, l[i - 1]) {
                    mask |= (1 << k[i - 1][i1]);
                }
                if(j & mask != mask) continue;
                rep(mask2, 0, 1 << K) {
                    if((mask2 | mask) == j) {
                        dp[i][j] = min(dp[i][j], dp[i - 1][mask2] + d[i - 1]);
                    }
                }
            }
        }
        ll ans = inf;
        rep(mask, 0, 1 << K) {
            vector<vector<P>> g(N * H);
            rep(i, 0, M) {
                if(mask & (1 << r[i])) {
                    rep(j, 0, H) {
                        if(j + h[i] >= H) break;
                        g[a[i] * H + j].push_back({b[i] * H + j + h[i], 0});
                        g[b[i] * H + j].push_back({a[i] * H + j + h[i], 0});
                    }
                } else {
                    rep(j, 0, H) {
                        if(j + h[i] >= H) continue;
                        g[a[i] * H + j].push_back({b[i] * H + j + h[i], c[i]});
                        g[b[i] * H + j].push_back({a[i] * H + j + h[i], c[i]});
                    }
                }
            }
            vector<ll> dist(N * H, inf);
            priority_queue<P, vector<P>, greater<P>> pq;
            dist[S * H] = 0;
            pq.push({dist[S * H], S * H});
            while(!pq.empty()) {
                auto [dis, cur] = pq.top();
                pq.pop();
                if(dist[cur] < dis) continue;
                for(const auto& [to, cost] : g[cur]) {
                    if(dist[to] > dist[cur] + cost) {
                        dist[to] = dist[cur] + cost;
                        pq.push({dist[to], to});
                    }
                }
            }
            ll res = inf;
            rep(i, 0, H) {
                res = min(res, dp[p][mask] + dist[T * H + i]);
            }
            ans = min(ans, res);
        }
        if(ans == inf) ans = -1;
        cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 7380
memory_kb: 4148
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using P = pair<ll, ll>;
#define rep(i, a, b) for(ll i = a; i < b; ++i)
#define rrep(i, a, b) for(ll i = a; i >= b; --i)
constexpr ll inf = 4e18;
int main(void) {
    cin.tie(0);
    ios::sync_with_stdio(0);
    while(true) {
        int N, M, H, K;
        cin >> N >> M >> H >> K;
        if(N == 0 and M == 0 and H == 0 and K == 0) break;
        H++;
        vector<int> a(M), b(M), c(M), h(M), r(M);
        rep(i, 0, M) {
            cin >> a[i] >> b[i] >> c[i] >> h[i] >> r[i];
            a[i]--;
            b[i]--;
            r[i]--;
        }
        int S, T;
        cin >> S >> T;
        S--;
        T--;
        int p;
        cin >> p;
        vector<int> l(p), d(p);
        vector<vector<int>> k(p);
        rep(i, 0, p) {
            cin >> l[i] >> d[i];
            k[i].resize(l[i]);
            rep(j, 0, l[i]) {
                cin >> k[i][j];
                k[i][j]--;
            }
        }
        vector<vector<int>> dp(p + 1, vector<int>(1 << K, 1e9));
        dp[0][0] = 0;
        rep(i, 1, p + 1) {
            rep(j, 0, 1 << K) {
                dp[i][j] = dp[i - 1][j];
                int mask = 0;
                rep(i1, 0, l[i - 1]) {
                    mask |= (1 << k[i - 1][i1]);
                }
                if(j & mask != mask) continue;
                rep(mask2, 0, 1 << K) {
                    if((mask2 | mask) == j) {
                        dp[i][j] = min(dp[i][j], dp[i - 1][mask2] + d[i - 1]);
                    }
                }
            }
        }
        ll ans = inf;
        rep(mask, 0, 1 << K) {
            vector<vector<P>> g(N * H);
            rep(i, 0, M) {
                if(mask & (1 << r[i])) {
                    rep(j, 0, H) {
                        if(j + h[i] >= H) break;
                        g[a[i] * H + j].push_back({b[i] * H + j + h[i], 0});
                        g[b[i] * H + j].push_back({a[i] * H + j + h[i], 0});
                    }
                } else {
                    rep(j, 0, H) {
                        if(j + h[i] >= H) continue;
                        g[a[i] * H + j].push_back({b[i] * H + j + h[i], c[i]});
                        g[b[i] * H + j].push_back({a[i] * H + j + h[i], c[i]});
                    }
                }
            }
            vector<ll> dist(N * H, inf);
            priority_queue<P, vector<P>, greater<P>> pq;
            dist[S * H] = 0;
            pq.push({dist[S * H], S * H});
            while(!pq.empty()) {
                auto [dis, cur] = pq.top();
                pq.pop();
                if(dist[cur] < dis) continue;
                for(const auto& [to, cost] : g[cur]) {
                    if(dist[to] > dist[cur] + cost) {
                        dist[to] = dist[cur] + cost;
                        pq.push({dist[to], to});
                    }
                }
            }
            ll res = inf;
            rep(i, 0, H) {
                res = min(res, dp[p][mask] + dist[T * H + i]);
            }
            ans = min(ans, res);
        }
        if(ans == inf) ans = -1;
        cout << ans << '\n';
    }
}
accuracy: 1
time_ms: 7340
memory_kb: 4172
final_rank: 18