// // Problem: 1 Day Passport // Solution by: MORI Shingo // // implement 21min // #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; static const long double EPS = 1e-9; static const long double PI = acos(-1.0); #define REP(i, n) for (int i = 0; i < (int)(n); i++) #define FOR(i, s, n) for (int i = (s); i < (int)(n); i++) #define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++) #define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++) #define MEMSET(v, h) memset((v), h, sizeof(v)) struct Edge { int src; int dest; int cost; int h; int company; Edge() {;} Edge(int src, int dest, int cost, int h, int company) : src(src), dest(dest), cost(cost), h(h), company(company) {;} bool operator<(const Edge &rhs) const { return cost > rhs.cost; } }; typedef vector Edges; typedef vector Graph; int K, C, N, M, S, T, H; int pass[300]; Graph g; bool visit[110][30]; int dist[110][30]; int main() { int test_case = 0; while (scanf("%d %d %d %d", &N, &M, &H, &K) > 0 && K > 0) { test_case++; MEMSET(pass, 0x0f); // Read Graph g = Graph(N); REP(i, M) { int a, b, c, h, m; int v = scanf("%d %d %d %d %d", &a, &b, &c, &h, &m); assert(v == 5); a--; b--; m--; g[a].push_back(Edge(a, b, c, h, m)); g[b].push_back(Edge(b, a, c, h, m)); } int v = scanf("%d %d", &S, &T); assert(v == 2); S--; T--; v = scanf("%d", &C); assert(v == 1); // Read Passport Set pass[0] = 0; REP(i, C) { int s, d; int v = scanf("%d %d", &s, &d); assert(v == 2); int ks = 0; REP(j, s) { int k; int v = scanf("%d", &k); k--; assert(v == 1); ks |= 1 << k; } pass[ks] = min(pass[ks], d); } REP(i, 1 << K) { REP(j, i) { int next = i | j; pass[next] = min(pass[next], pass[i] + pass[j]); } } // Dijkstra int ans = 1LL << 30; REP(p, 1 << K) { if (pass[p] >= 0x0f0f0f0f) { continue; } MEMSET(visit, false); MEMSET(dist, 0x0f); priority_queue que; que.push(Edge(S, S, pass[p], 0, 0)); while (!que.empty()) { Edge e = que.top(); que.pop(); int from = e.dest; if (visit[from][e.h]) { continue; } visit[from][e.h] = true; if (from == T) { ans = min(ans, e.cost); break; } FORIT(it, g[from]) { int to = it->dest; int ncost = e.cost + it->cost; int nh = e.h + it->h; if (p & (1 << it->company)) { ncost -= it->cost; } if (nh > H || visit[to][nh] || dist[to][nh] <= ncost) { continue; } dist[to][nh] = ncost; que.push(Edge(from, to, ncost, nh, 0)); } } } // print ans if (ans < (1LL << 30)) { printf("%d\n", ans); } else { puts("-1"); } } assert(test_case <= 150); }