/*
    題意:有錢w,給出n種選擇,每種選擇有m[i]個物品,但必須先買盒子,價格p[i]
            然后給出每種選擇的一些物品的價格還有價值   求取得最大值

    一開始我想用兩個數組,一個記錄已經買了box的,一個還沒的
    這樣子轉移時有兩種
    但注意有0的數據,被題目蒙了.

    下面的是龍教主的做法,比較簡潔
    由于要買box,就先更新一下以前的數組,使得dp[j+p[i]] = _dp[j]
    _dp[]最后要更新下,保存最優值
  
 
  背包變形加狀態做,方便點?hdu 3236也是加狀態做
*/

#include
<cstdio>
#include
<cstring>
#include
<algorithm>
using namespace std;

inline 
int max(int a,int b){return a>b?a:b;}

const int MAXN = 100010;
const int INF = 1000000000;

int dp[MAXN],_dp[MAXN];//within n ,  without n
int p[51],m[51],c[51][11],v[51][11];

int main()
{
    
//freopen("in","r",stdin);
    int n,w;
    
while(~scanf("%d%d",&n,&w))
    
{
        
for(int i=1;i<=n;i++)
        
{
            scanf(
"%d%d",&p[i],&m[i]);
            
for(int j=1;j<=m[i];j++)
                scanf(
"%d%d",&c[i][j],&v[i][j]);
        }

        
for(int j=0;j<=w;j++)dp[j] = _dp[j] = 0;
        
for(int i=1;i<=n;i++)
        
{
            
for(int j=0;j+p[i]<=w;j++)dp[j+p[i]] = _dp[j];//由于需要先買box,要先更新可以枚舉的起點
            for(int k=1;k<=m[i];k++)
                
for(int j=w;j>=p[i]+c[i][k];j--)
                    dp[j] 
= max(dp[j],dp[j-c[i][k]]+v[i][k]);
            
for(int j=p[i];j<=w;j++)//前i次的最優值
                _dp[j] = max(_dp[j],dp[j]);
        }

        
int ans = 0;
        
for(int j=0;j<=w;j++)
            ans 
= max(ans,_dp[j]);
        printf(
"%d\n",ans);
    }

    
return 0;
}


/*

    之前的做法跟上面的類似
    不過轉移時分兩種: 從沒有box的,從有box的轉移過來
    for(int j=0;j<=w;j++)
    {
        dp[now][j] = -INF;
        _dp[now][j] = max(dp[pre][j],_dp[pre][j]);
    }
    for(int k=1;k<=m[i];k++)
        for(int j=w;j>=p[i]+c[i][k];j--)
        {
            //注意有0的數據,所以要按照下面的順序
            //反過來的話,會錯,因為dp[now][j-c[i][k]]可能被更新過了,不是之前的值了
            dp[now][j] = max(dp[now][j],dp[now][j-c[i][k]]+v[i][k]);
            dp[now][j] = max(dp[now][j],_dp[now][j-p[i]-c[i][k]]+v[i][k]);
        }   
*/