/*
    题意:有钱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]);
        }   
*/