Problem:
MathJax.Hub.Config({ tex2jax: { inlineMath: [["$","$"], ["\\(","\\)"]], processEscapes: true }});

一日乗車券

某国に住む大学生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

Solution in Ruby (judge verdict: Runtime Error)

class Heap
	require 'forwardable'
	extend Forwardable

	def initialize
		@array = []
		@index = {}
	end

	def add(obj, key)
		@array << [obj, key]
		@index[obj] = @array.size - 1
		lift_up(@array.size - 1)
	end

	def swap(i, j)
		u = @array[i]
		v = @array[j]
		@index[u[0]], @index[v[0]] = j, i
		@array[i], @array[j] = v, u
	end

	def lift_up(i)
		return if i == 0
		j = (i - 1) / 2
		if (@array[i][1] <=> @array[j][1]) < 0
			swap(i, j)
			lift_up(j)
		end
	end

	def del_min
		raise "heap is empty!" if empty?
		min = @array[0]
		if size > 1
			swap(0, @array.size-1)
			@array.pop
			lift_down(0)
		else
			@array.pop
		end
		@index.delete(min[0])
		min
	end

	def inc_key(obj, diff)
		i = @index[obj]
		@array[i][1] += diff
		lift_down(i)
	end

	def dec_key(obj, diff)
		i = @index[obj]
		@array[i][1] -= diff
		lift_up(i)
	end

	def update_key(obj, new_key)
		i = @index[obj]
		return unless i
		return if (new_key <=> @array[i][1]) >= 0
		@array[i][1] = new_key
		lift_up(i)
	end

	def min_obj
		@array[0][0]
	end

	def min_key
		@array[0][1]
	end

	def lift_down(i)
		j = 2 * i + 1
		k = j + 1
		if k >= size
			return if j >= size
			if (@array[i][1] <=> @array[j][1]) > 0
				swap(i, j)
				lift_down(j)
			end
		else
			l = ((@array[j][1] <=> @array[k][1]) < 0 ? j : k)
			if (@array[i][1] <=> @array[l][1]) > 0
				swap(i, l)
				lift_down(l)
			end
		end
	end

	def_delegators :@array, :empty?, :size
end

module Graphical
	require 'set'

	def reachable_from(s, max_depth = nil)
		reached = Set[s]
		queue = [s]
		depth = 0
		loop {
			break if max_depth && depth >= max_depth
			next_queue = []
			until queue.empty?
				u = queue.shift
				each_out_connection_of(u){|v, _|
					next if reached.include?(v)
					reached << v
					next_queue << v
				}
			end
			break if next_queue.empty?
			queue = next_queue
			depth += 1
		}
		return reached
	end

	def bfs(start)
		raise "start must be Enumerable" if !start.kind_of?(Enumerable)
		reached = Set[*start.to_a]
		queue = []
		start.each{|s| queue << s}
		dist = {}
		loop.with_index {|_, depth|
			next_queue = []
			until queue.empty?
				u = queue.shift
				return depth if block_given? && yield(u, depth)
				dist[u] = depth
				each_out_connection_of(u){|v, _|
					next if reached.include?(v)
					reached << v
					next_queue << v
				}
			end
			break if next_queue.empty?
			queue = next_queue
		}
		return dist
	end

	def dijkstra(start)
		raise "start must be Enumerable" if !start.kind_of?(Enumerable)
		h = Heap.new
		reached = Set[*start.to_a]
		start.each{|s| h.add(s, 0)}

		dist = {}
		until h.empty?
			u, key = h.del_min
			return key if block_given? && yield(u, key)
			dist[u] = key
			each_out_connection_of(u){|v, l|
				d = dist[u] + l
				if reached.include?(v)
					h.update_key(v, d)
				else
					h.add(v, d)
					reached << v
				end
			}
		end
		block_given? ? nil : dist
	end

	def bidir_dijkstra(s, t)
		f_dist = {}
		b_dist = {}

		f_heap = Heap.new
		b_heap = Heap.new

		f_heap.add(s, 0)
		b_heap.add(t, 0)

		f_reached = Set[s]
		b_reached = Set[t]

		f_current_dist = b_current_dist = 0
		best = Float::INFINITY

		loop {
			if !f_heap.empty?
				u, key = f_heap.del_min
				f_dist[u] = key
				f_current_dist = key
				each_out_connection_of(u){|v, l|
					d = f_dist[u] + l
					if b_dist[v]
						path_len = d + b_dist[v]
						best = path_len if path_len < best
					end
					if f_reached.include?(v)
						f_heap.update_key(v, d)
					else
						f_heap.add(v, d)
						f_reached << v
					end
				}
			end

			if !b_heap.empty?
				u, key = b_heap.del_min
				b_dist[u] = key
				b_current_dist = key
				each_in_connection_of(u){|v, l|
					d = b_dist[u] + l
					if f_dist[v]
						path_len = d + f_dist[v]
						best = path_len if path_len < best
					end
					if b_reached.include?(v)
						b_heap.update_key(v, d)
					else
						b_heap.add(v, d)
						b_reached << v
					end
				}
			end

			return best if f_current_dist + b_current_dist >= best
			return nil if f_heap.empty? && b_heap.empty?
		}
	end

	def a_star(start)
		raise "a_star need termination condition" unless block_given?
		h = Heap.new
		reached = Set[start]
		h.add(start, [a_star_heuristic(start), 0])

		dist = {}
		until h.empty?
			u, (e, d) = h.del_min
			return d if yield(u, dist)
			dist[u] = d
			each_out_connection_of(u){|v, l|
				d = dist[u] + l
				e = d + a_star_heuristic(v)
				if reached.include?(v)
					h.update_key(v, [e, d])
				else
					h.add(v, [e, d])
					reached << v
				end
			}
		end
		block_given? ? nil : dist
	end

	#make_variations :bidir_dijkstra

	def prim(start)
		h = Heap.new
		h.add(start, 0)
		reached = Set[start]
		tree_len = 0

		until h.empty?
			u, key = h.del_min
			tree_len += key

			each_connection_of(u){|v, d|
				if reached.include?(v)
					h.update_key(v, d)
				else
					h.add(v, d)
					reached << v
				end
			}
		end
		tree_len
	end

	def each_layer_from(start)
		raise "start must be Enumerable" if !start.kind_of?(Enumerable)
		return enum_for(__method__, start) unless block_given?
		reached = Set[*start]
		current_layer = start

		loop {
			yield current_layer
			next_layer = []
			current_layer.each{|u|
				each_out_connection_of(u){|v|
					next if reached.include?(v)
					reached << v
					next_layer << v
				}
			}	

			return if next_layer.empty?
			current_layer = next_layer
		}
	end
end

class Graph
	include Graphical

	def initialize(*options)
		@options = Set[*options]
	end

	def add_node(property = {})
		Node.new(property)
	end

	def add_edge(u, v, property = {})
		e = Edge.new(u, v, property)
		u.add_edge(e)
		v.add_edge(e)
		e
	end
	
	def del_edge(e)
		u, v = e.opposite.keys
		u.del_edge(e)
		v.del_edge(e)
		e
	end

	class Node
		def initialize(property)
			@property = property
			@edges = Set.new
		end

		def add_edge(e)
			@edges << e
		end

		def del_edge(e)
			@edges.delete(e)
		end

		def to_s
			@property[:name] || super
		end

		def each_edge
			@edges.each{|e| 
				yield e
			}
		end

		attr_reader :property
	end

	class Edge
		def initialize(u, v, property)
			@opposite = {u => v, v => u}
			@property = property
		end
		attr_reader :opposite, :property

		def to_s
			@property[:name] || super
		end

		def length
			@property[:length] || 1
		end
	end

	def each_out_connection_of(u)
		u.each_edge{|e|
			yield(e.opposite[u], e.length)
		}
	end

	alias :each_in_connection_of :each_out_connection_of
end

def compute_portfolio(passports, n)
	max = (1 << n) - 1	
	table = (0..1).map{ Array.new(max+1, Float::INFINITY) }
	table[0][0] = 0
	table[1][0] = 0
	for i in 0..passports.size-1
		c, bits = passports[i]
		for j in 0..max
			table[1][j] = table[0][j] if table[0][j] < table[1][j] 
			x = table[0][j] + c
			table[1][j | bits] = x if x < table[1][j | bits]
		end
		table << table.shift
	end
	table[0]
end

loop {
	n, m, available_time, k = gets.split.map &:to_i
	break if n == 0

	g = Graph.new
	nodes = (0..n).map{ g.add_node }
	edges = []
	m.times{
		a, b, c, h, r = gets.split.map &:to_i
		edges << g.add_edge(nodes[a], nodes[b], {:cost => c, :time => h, :company => r})
	}

	start, goal = gets.split.map &:to_i

	p_num = gets.to_i
	passports = []
	p_num.times {
		_, price, *companies = gets.split.map &:to_i
		bits = 0
		companies.each{|i| bits |= (1 << i-1)}
		passports << [price, bits]
	}

	portfolio = compute_portfolio(passports, k)

	(0..portfolio.size-1).zip(portfolio).select{|x, y| y < 1000000}.map{|x,y| [x.to_s(2), y]}

	min_cost = Float::INFINITY
	(0..(1<<k)-1).each{|x|
		next if portfolio[x] == Float::INFINITY
		passport_cost = portfolio[x]

		edges.each{|e|
			k = e.property[:company] - 1
			e.property[:length] = (x[k] == 1 ? 0 : e.property[:cost])
		}

		include Graphical
		def each_out_connection_of(node)
			u, rest_time = node
			u.each_edge{|e|
				if rest_time >= e.property[:time]
					yield([e.opposite[u], rest_time - e.property[:time]], e.property[:length])
				end
			}
		end

		road_cost = (dijkstra([[nodes[start], available_time]]){|(v, _), _| v == nodes[goal]} || Float::INFINITY)
		total_cost = passport_cost + road_cost
		min_cost = total_cost if total_cost < min_cost
	}

	p min_cost == Float::INFINITY ? -1 : min_cost
}