/*input
5
3
1 6
1 7
1 5
2
1 4
1 3
3
1 10
3 5
2 3
3
1 15
2 4
1 10
1
1 100

*/
/*

**************************
*						 *
* AUTHOR :: knight_coder *
*						 *
**************************

*/
#include<bits/stdc++.h>
#define lld          long long int
#define pb          push_back
#define ppb         pop_back
#define	endl		'\n'
#define mii         map<lld,lld>
#define msi         map<string,lld>
#define mis         map<lld, string>
#define mpi         map<pair<lld ,lld >,lld >
#define pii         pair<lld,lld>
#define vi          vector<lld>
#define vpi 		vector<pii>
#define vs          vector<string>
#define all(a)      (a).begin(),(a).end()
#define F           first
#define S           second
#define sz(x)       (lld)x.size()
#define hell        1000000007
#define rrep(i,m,n)	for(lld i=m;i>=n;i--)
#define rep(i,m,n)	for(lld i=m;i<n;i++)
#define lbnd        lower_bound
#define ubnd        upper_bound
#define bs          binary_search
#define mp          make_pair
#define what_is(x)  cerr << #x << " is " << x << endl;
#define pr(x) 		cout<< x << " ";
#define pre(x)		cout<< x << endl ;
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
// template<typename T>
// using ordered_set = tree<T,null_type,less<T>,rb_tree_tag,tree_order_statistics_node_update>; 
//change null_type to get ordered_map
using namespace std;
#define N  100005
lld dp[N][12];
void inii()
{
	rep(i,0,N)
	{
		rep(j,0,12)
		{
			dp[i][j]=-1;
		}
	}
}
vi turn[N][4];
lld n;
lld solve2(lld pos,lld chan)
{
	if(pos==n)
	{
		return 0;
	}
	if(dp[pos][chan]!=-1)
	{
		return dp[pos][chan];
	}
	lld ans=0;
	if(chan%10==0)
	{
		if(turn[pos][3].size())
		{
			ans=max(2*turn[pos][3][0]+solve2(pos+1,(chan+1)%10),ans);
		}	
		if(turn[pos][2].size()>0 && turn[pos][1].size()>0)
		{
			ans=max(2*max(turn[pos][2][0],turn[pos][1][0]) + min(turn[pos][2][0],turn[pos][1][0])+solve2(pos+1,(chan+2)%10),ans);
		}
		if(turn[pos][2].size()>0)
		{
			ans=max(ans,2*turn[pos][2][0]+solve2(pos+1,(chan+1)%10));
		}
		if(turn[pos][1].size()>0)
		{
			ans=max(ans,2*turn[pos][1][0]+solve2(pos+1,(chan+1)%10));
		}
		if(turn[pos][1].size()>=3)
		{
			ans=max(ans,2*turn[pos][1][0]+turn[pos][1][1]+turn[pos][1][2]+solve2(pos+1,(chan+3)%10));
		}
		if(turn[pos][1].size()>=2)
		{
			ans=max(ans,2*turn[pos][1][0]+turn[pos][1][1]+solve2(pos+1,(chan+2)%10));
		}
		if(turn[pos][1].size()>=1)
		{
			ans=max(ans,2*turn[pos][1][0]+solve2(pos+1,(chan+1)%10));
		}
		ans=max(ans,solve2(pos+1,(chan)%10));
	}
	if((chan+1)%10==0)
	{
		if(turn[pos][3].size())
		{
			ans=max(turn[pos][3][0]+solve2(pos+1,(chan+1)%10),ans);
		}
		if(turn[pos][2].size()>0 && turn[pos][1].size()>0)
		{
			ans=max(2*max(turn[pos][2][0],turn[pos][1][0]) + min(turn[pos][2][0],turn[pos][1][0])+solve2(pos+1,(chan+2)%10),ans);			
		}
		if(turn[pos][2].size()>0)
		{
			ans=max(ans,turn[pos][2][0]+solve2(pos+1,(chan+1)%10));
		}
		if(turn[pos][1].size()>0)
		{
			ans=max(ans,turn[pos][1][0]+solve2(pos+1,(chan+1)%10));
		}
		if(turn[pos][1].size()>=3)
		{
			ans=max(ans,2*turn[pos][1][0]+turn[pos][1][1]+turn[pos][1][2]+solve2(pos+1,(chan+3)%10));
		}	
		if(turn[pos][1].size()>=2)
		{
			ans=max(ans,2*turn[pos][1][0]+turn[pos][1][1]+solve2(pos+1,(chan+2)%10));
		}
		if(turn[pos][1].size()>=1)
		{
			ans=max(ans,turn[pos][1][0]+solve2(pos+1,(chan+1)%10));
		}
	}	
	if((chan+2)%10==0)
	{	
		if(turn[pos][3].size())
		{
			ans=max(turn[pos][3][0]+solve2(pos+1,(chan+1)%10),ans);
		}
		if(turn[pos][2].size()>0 && turn[pos][1].size()>0)
		{
			ans=max(max(turn[pos][2][0],turn[pos][1][0]) + min(turn[pos][2][0],turn[pos][1][0])+solve2(pos+1,(chan+2)%10),ans);			
		}
		if(turn[pos][2].size()>0)
		{
			ans=max(ans,turn[pos][2][0]+solve2(pos+1,(chan+1)%10));
		}
		if(turn[pos][1].size()>0)
		{
			ans=max(ans,turn[pos][1][0]+solve2(pos+1,(chan+1)%10));
		}
		if(turn[pos][1].size()>=3)
		{
			ans=max(ans,2*turn[pos][1][0]+turn[pos][1][1]+turn[pos][1][2]+solve2(pos+1,(chan+3)%10));
		}	
		if(turn[pos][1].size()>=2)
		{
			ans=max(ans,turn[pos][1][0]+turn[pos][1][1]+solve2(pos+1,(chan+2)%10));
		}
		if(turn[pos][1].size()>=1)
		{
			ans=max(ans,turn[pos][1][0]+solve2(pos+1,(chan+1)%10));
		}
		ans=max(ans,solve2(pos+1,(chan)%10));
	}
	if(true)
	{
		if(turn[pos][3].size())
		{
			ans=max(turn[pos][3][0]+solve2(pos+1,(chan+1)%10),ans);
		}
		if(turn[pos][2].size()>0 && turn[pos][1].size()>0)
		{
			ans=max(max(turn[pos][2][0],turn[pos][1][0]) + min(turn[pos][2][0],turn[pos][1][0])+solve2(pos+1,(chan+2)%10),ans);			
		}
		if(turn[pos][2].size()>0)
		{
			ans=max(ans,turn[pos][2][0]+solve2(pos+1,(chan+1)%10));
		}
		if(turn[pos][1].size()>0)
		{
			ans=max(ans,turn[pos][1][0]+solve2(pos+1,(chan+1)%10));
		}
		if(turn[pos][1].size()>=3)
		{
			ans=max(ans,turn[pos][1][0]+turn[pos][1][1]+turn[pos][1][2]+solve2(pos+1,(chan+3)%10));
		}	
		if(turn[pos][1].size()>=2)
		{
			ans=max(ans,turn[pos][1][0]+turn[pos][1][1]+solve2(pos+1,(chan+2)%10));
		}
		if(turn[pos][1].size()>=1)
		{
			ans=max(ans,turn[pos][1][0]+solve2(pos+1,(chan+1)%10));
		}
		ans=max(ans,solve2(pos+1,(chan)%10));		
	}
	dp[pos][chan]=ans;
	return ans;
}
void solve()
{
	inii();
	cin >> n;
	rep(i,0,n)
	{
		lld k;
		cin >> k;
		vi v1,v2,v3;
		rep(j,0,k)
		{
			lld c,d;
			cin >> c >> d;
			if(c==1)
			{
				v1.pb(d);
			}
			else if(c==2)
			{
				v2.pb(d);
			}
			else if(c==3)
			{
				v3.pb(d);
			}
		}
		sort(all(v1)),sort(all(v2));
		sort(all(v3));
		reverse(all(v1)),reverse(all(v2)),reverse(all(v3));
		lld cn=0;
		for(auto j:v1)
		{
			turn[i][1].pb(j);
			cn++;
			if(cn==3)
			{
				break;
			}
		}
		if(v2.size())
		{
			turn[i][2].pb(v2[0]);
		}
		if(v3.size())
		{
			turn[i][3].pb(v3[0]);
		}
	} 
	cout << solve2(0,1) << endl;
}
int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int tests=1;
	//cin>>tests;
	while(tests--)
	{
		solve();
	}
}