# 朴素解法
def bagGrouped(N,V,v_arr,w_arr,s_arr):
#初始化dp数组
dp = [[0 for i in range(V+1)] for j in range(N+1)]
for i in range(1,N+1): # 遍历所有物品组
for j in range(1,V+1): # 遍历体积阈值,正序遍历
for s in range(0,s_arr[i-1]): # 遍历第i组物品的所有s_arr[i-1]个物品
dp[i][j] = max(dp[i-1][j], dp[i][j]) # !!!出错:在遍历s_arr时,为了防止dp[i][j]多次被dp[i-1][j]覆盖,所以这里要取max(dp[i-1][j], dp[i][j]),而不能只是dp[i-1][j]
if j>=v_arr[i-1][s]:
dp[i][j] = max(dp[i][j], dp[i-1][j-v_arr[i-1][s]] + w_arr[i-1][s])
return dp[-1][-1]
# 输入样例
N, V = map(int,input().split()) # N表示物品组数,V表示背包容量
v_arr = [[] for i in range(N)] # 输入技巧,v_arr初始化为二维空列表,第i维表示第i组物品的各物品体积
w_arr = [[] for i in range(N)] # 输入技巧,_arr初始化为二维空列表,第i维表示第i组物品的各物品价值
s_arr = [] # 存储每组物品数量
for i in range(N):
s_arr.append(int(input().strip()))
for j in range(s_arr[i]):
in_li = list(map(int, input().split()))
v_arr[i].append(in_li[0])
w_arr[i].append(in_li[1])
print(bagGrouped(N,V,v_arr,w_arr,s_arr))
# 空间优化解法
# 输入样例
N, V = map(int,input().split()) # N表示物品组数,V表示背包容量
v_arr = [[] for i in range(N)] # 输入技巧,v_arr初始化为二维空列表,第i维表示第i组物品的各物品体积
w_arr = [[] for i in range(N)] # 输入技巧,_arr初始化为二维空列表,第i维表示第i组物品的各物品价值
s_arr = [] # 存储每组物品数量
for i in range(N):
s_arr.append(int(input().strip()))
for j in range(s_arr[i]):
in_li = list(map(int, input().split()))
v_arr[i].append(in_li[0])
w_arr[i].append(in_li[1])
#初始化dp数组
dp = [0 for i in range(V+1)] # !!!出错,范围是[0,V],而不是[0,N]
for i in range(1,N+1): # 遍历所有物品组
for j in range(V,0,-1): # 遍历体积阈值,倒序遍历
for s in range(s_arr[i-1]): # 遍历第i组物品的所有s_arr[i-1]个物品
# print(i,j,s)
# print(v_arr[i-1][s-1])
# print(j-v_arr[i-1][s-1])
if j>=v_arr[i-1][s]:
dp[j] = max(dp[j], dp[j-v_arr[i-1][s]] + w_arr[i-1][s])
# print(dp)
dp[-1]