import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;

import javax.sound.sampled.ReverbType;

import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
public class cf1{
	static public int GCD(int a, int b) {
		   if (b==0) return a;
		   return GCD(b,a%b);
		}
	static boolean[]prime;
	static ArrayList<Integer> primes;
	static void sieveOfEratosthenes(int n)
    {
        prime = new boolean[n+1];
        for(int i=0;i<=n;i++)
            prime[i] = true;

        for(int p = 2; p <=n; p++)
        {

            if(prime[p])
            {
                //ans[(int)p]=c;
            	primes.add(p);
                for(long i = p*1l*p; i <= n; i += p) {
                	//if(ans[i]System.out.println(i);
                    prime[(int)i] = false;

                }
                //c++;
            }
        }

    }
	static void dfs(int i,int p) {
		v[i]=true;
		if(p==0) {
			zero.add(i+1);
		}
		else {
			one.add(i+1);
		}
		for(int j:adj[i]) {
			if(!v[j])
				dfs(j,p^1);
		}
	}
	static boolean[]v;
	static LinkedList<Integer>[]adj;
	static LinkedList<Integer>zero;
	static LinkedList<Integer>one;

	static long[][]block;
	public static void main(String[] args) throws IOException {
		MScanner sc=new MScanner(System.in);
		//BufferedReader br=new BufferedReader((new InputStreamReader(System.in)));
		PrintWriter pw=new PrintWriter(System.out);
		n=sc.nextInt();
		block=new long[n][5];
		for(int i=0;i<n;i++) {
			int k=sc.nextInt();
			PriorityQueue<Integer>one=new PriorityQueue<Integer>(Collections.reverseOrder());
			PriorityQueue<Integer>two=new PriorityQueue<Integer>(Collections.reverseOrder());
			PriorityQueue<Integer>three=new PriorityQueue<Integer>(Collections.reverseOrder());
			for(int j=0;j<k;j++) {
				int c=sc.nextInt();
				if(c==1) {
					one.add(sc.nextInt());
				}
				else {
					if(c==2) {
						two.add(sc.nextInt());
					}
					else {
						three.add(sc.nextInt());
					}
				}
			}
			long max1=(long)(-7e9);
			if(one.size()!=0)
				max1=one.poll();
			long max11=(long)(-7e9);
			if(one.size()!=0)
				max11=one.poll();
			long max111=(long)(-7e9);
			if(one.size()!=0) {
				max111=one.poll();
			}
			long max2=(long)(-7e9);
			if(two.size()>0) {
				max2=two.poll();
			}
			long max3=(long)(-7e9);
			if(three.size()>0) {
				max3=three.poll();
			}
			block[i][0]=Math.max(Math.max(max1,max2),max3);
			block[i][1]=Math.max(max1+max11,max1+max2);
			block[i][2]=max1+max11+max111;
			block[i][3]=Math.max(max1*2+max11,Math.max(max1+max2*2,max1*2+max2));
			block[i][4]=max1*2+max11+max111;
		}
		memo=new long[n][10];
		for(int i=0;i<n;i++) {
			Arrays.fill(memo[i],-1);
			//System.out.println(block[i][0]+" "+block[i][1]+" "+block[i][2]+" "+block[i][3]+" "+block[i][4]);
		}
		pw.println(dp(0,0));
		pw.flush();

	}
	static long[][]memo;
	static int n;
	static long dp(int i,int taken) {
		if(i==n)return 0;
		if(memo[i][taken]!=-1)return memo[i][taken];
		if(taken==7) {
			return memo[i][taken]=Math.max(Math.max(dp(i+1,0)+block[i][4],dp(i+1,taken)),Math.max(dp(i+1,8)+block[i][0],dp(i+1,9)+block[i][1]));
		}
		if(taken==8) {
			return memo[i][taken]=Math.max(Math.max(dp(i+1,0)+block[i][3],dp(i+1,taken)),Math.max(dp(i+1,1)+block[i][4],dp(i+1,9)+block[i][0]));
		}
		if(taken==9) {
			return memo[i][taken]=Math.max(Math.max(dp(i+1,0)+2*block[i][0],dp(i+1,taken)),Math.max(dp(i+1,1)+block[i][3],dp(i+1,2)+block[i][4]));
		}
		return memo[i][taken]=Math.max(Math.max(dp(i+1,(taken+1)%10)+block[i][0],dp(i+1,taken)),Math.max(dp(i+1,(taken+2)%10)+block[i][1],dp(i+1,(taken+3)%10)+block[i][2]));
	}
	static class tri implements Comparable<tri>{
    	int l;int idx;
    	tri(int x,int z){
    		l=x;idx=z;
    	}
		@Override
		public int compareTo(tri o) {
			if(l!=o.l) {
				if(l>o.l)return 1;
				return -1;
			}
			return idx-o.idx;
		}
		public boolean equals(tri o) {
			if(this.compareTo(o)==0)return true;
			return false;
		}
		public String toString() {
			return "("+l+" "+idx+")";
		}
    }
	static class MScanner
	{
	    StringTokenizer st;
	    BufferedReader br;

	    public MScanner(InputStream s){    br = new BufferedReader(new InputStreamReader(s));}

	    public String next() throws IOException
	    {
	        while (st == null || !st.hasMoreTokens())
	            st = new StringTokenizer(br.readLine());
	        return st.nextToken();
	    }

	    public int nextInt() throws IOException {return Integer.parseInt(next());}

	    public long nextLong() throws IOException {return Long.parseLong(next());}

	    public String nextLine() throws IOException {return br.readLine();}

	    public double nextDouble() throws IOException
	    {
	        String x = next();
	        StringBuilder sb = new StringBuilder("0");
	        double res = 0, f = 1;
	        boolean dec = false, neg = false;
	        int start = 0;
	        if(x.charAt(0) == '-')
	        {
	            neg = true;
	            start++;
	        }
	        for(int i = start; i < x.length(); i++)
	            if(x.charAt(i) == '.')
	            {
	                res = Long.parseLong(sb.toString());
	                sb = new StringBuilder("0");
	                dec = true;
	            }
	            else
	            {
	                sb.append(x.charAt(i));
	                if(dec)
	                    f *= 10;
	            }
	        res += Long.parseLong(sb.toString()) / f;
	        return res * (neg?-1:1);
	    }

	    public boolean ready() throws IOException {return br.ready();}

	}
}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "5\n" +
      "3\n" +
      "1 6\n" +
      "1 7\n" +
      "1 5\n" +
      "2\n" +
      "1 4\n" +
      "1 3\n" +
      "3\n" +
      "1 10\n" +
      "3 5\n" +
      "2 3\n" +
      "3\n" +
      "1 15\n" +
      "2 4\n" +
      "1 10\n" +
      "1\n" +
      "1 100";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();
        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= 9 || j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= 9 || j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= 9 || j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    //    ZZ.showIntegerArray(sums);
    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    showIntegerArray(sums);
    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

  public static void showIntegerArray(long[] a) {
    if (a.length == 0) {
      System.out.println("[]");
    } else {
      System.out.printf("[");
      for (int i = 0; i < a.length; i++) {
        System.out.printf("%4d", a[i]);
      }
      System.out.println("]");
    }
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();
    // if (n == 200000) System.out.println(n);

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();
      if (n > 5 && k>1) System.out.println(k);

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();
        // if (n == 200000) System.out.printf("%d %d\n", c, d);

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        largestS = Math.max(largestS, sums[j]); // also have to take the largest of sums, same as playing 'zero' cards
        sums[j] = largestS;
      }
    }

    // if (n == 200000) showIntegerArray(sums);

    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

  public static void showIntegerArray(long[] a) {
    for (long l : a) {
      System.out.println(l);
    }
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();
    // if (n == 200000) System.out.println(n);

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();
      //      if (n > 5 && k>1) System.out.println(k);

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();
        // if (n == 200000) System.out.printf("%d %d\n", c, d);

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        largestS = Math.max(largestS, sums[j]); // also have to take the largest of sums, same as playing 'zero' cards
        sums[j] = largestS;
      }
    }

    // if (n == 200000) showIntegerArray(sums);

    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

  public static void showIntegerArray(long[] a) {
    for (long l : a) {
      System.out.println(l);
    }
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();
    // if (n == 200000) System.out.println(n);

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();
      if (n > 5 && k>1) System.out.println(k);

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();
        // if (n == 200000) System.out.printf("%d %d\n", c, d);

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    // if (n == 200000) showIntegerArray(sums);

    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

  public static void showIntegerArray(long[] a) {
    for (long l : a) {
      System.out.println(l);
    }
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "5\n" +
      "3\n" +
      "1 6\n" +
      "1 7\n" +
      "1 5\n" +
      "2\n" +
      "1 4\n" +
      "1 3\n" +
      "3\n" +
      "1 10\n" +
      "3 5\n" +
      "2 3\n" +
      "3\n" +
      "1 15\n" +
      "2 4\n" +
      "1 10\n" +
      "1\n" +
      "1 100";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();
        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    //    ZZ.showIntegerArray(sums);
    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    //    ZZ.showIntegerArray(sums);
    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();
    // if (n == 200000) System.out.println(n);

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();
      if (n == 200000 && k>1) System.out.println(k);

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();
        // if (n == 200000) System.out.printf("%d %d\n", c, d);

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    // if (n == 200000) showIntegerArray(sums);

    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

  public static void showIntegerArray(long[] a) {
    for (long l : a) {
      System.out.println(l);
    }
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    if (n == 200000) showIntegerArray(sums);

    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

  public static void showIntegerArray(long[] a) {
    if (a.length == 0) {
      System.out.println("[]");
    } else {
      System.out.printf("[");
      for (int i = 0; i < a.length; i++) {
        System.out.printf("%4d", a[i]);
      }
      System.out.println("]");
    }
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    if (n == 200000) showIntegerArray(sums);

    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

  public static void showIntegerArray(long[] a) {
    for (long l : a) {
      System.out.println(l);
    }
  }

}


import java.io.ByteArrayInputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class F {

  static boolean LOCAL = System.getProperty("ONLINE_JUDGE") == null;
  public static void main(String[] args) throws Exception {
    new F().go();
  }

  Scanner in;
  String INPUT = "7\n" +
      "1\n" +
      "3 413253320\n" +
      "1\n" +
      "1 772368544\n" +
      "1\n" +
      "2 22412126\n" +
      "1\n" +
      "1 548792648\n" +
      "1\n" +
      "2 166750218\n" +
      "1\n" +
      "3 912143029\n" +
      "1\n" +
      "3 739148297";

  void go() {
    if (LOCAL) {
      System.setIn(new ByteArrayInputStream(INPUT.getBytes()));
    }
    in = new Scanner(System.in);
    long startTime = System.currentTimeMillis();
    solve();
    if (LOCAL) {
      System.out.printf("[%dms]", System.currentTimeMillis()-startTime);
    }
    in.close();
  }

  PrintWriter out = new PrintWriter(System.out);
  StringBuffer sb = new StringBuffer();

  void solve() {

    int n = in.nextInt();
    if (n == 200000) System.out.println(n);

    int maxCards = 0;
    long[] sums = new long[10];

    for (int i = 0; i < n; i++) {
      int k = in.nextInt();
      if (n == 200000) System.out.println(k);

      List<Long> oneCards = new ArrayList<>();
      long twoCard = 0;
      long threeCard = 0;

      for (int j = 0; j < k; j++) {
        int c = in.nextInt();
        long d = in.nextLong();
        if (n == 200000) System.out.printf("%d %d\n", c, d);

        if (c==1) {
          insertCard(oneCards, d);
        }
        if (c==2) {
          twoCard = Math.max(twoCard, d);
        }
        if (c==3) {
          threeCard = Math.max(threeCard, d);
        }
      }

      int nrCards = 1;
      long[][] cardSums = new long[4][2];

      long biggestCard = Math.max(biggest(oneCards), twoCard);
      biggestCard = Math.max(biggestCard, threeCard);
      cardSums[1][0] = biggestCard;
      cardSums[1][1] = biggestCard * 2;

      int nrOnes = oneCards.size();
      if (nrOnes >= 2 || (nrOnes == 1 && twoCard > 0)) {
        nrCards = 2;
        long high1 = 0;
        long high2 = 0;
        if (twoCard > 0 && twoCard >= secBiggest(oneCards)) {
          high1 = Math.max(biggest(oneCards), twoCard);
          high2 = Math.min(biggest(oneCards), twoCard);
        } else {
          high1 = biggest(oneCards);
          high2 = secBiggest(oneCards);
        }
        cardSums[2][0] = high1 + high2;
        cardSums[2][1] = 2*high1 + high2;
      }

      if (nrOnes == 3) {
        nrCards = 3;
        long h1 = oneCards.get(2);
        long h2 = oneCards.get(1);
        long h3 = oneCards.get(0);
        cardSums[3][0] = h1 + h2 + h3;
        cardSums[3][1] = 2*h1 + h2 + h3;
      }

      maxCards += nrCards;
      maxCards = Math.min(maxCards, 9);
      long[] sums1 = new long[10];
      long[] sums2 = new long[10];
      long[] sums3 = new long[10];

      //always do sums1
      for (int j=1; j <= maxCards; j++) {
        sums1[j] = sums[j-1]+cardSums[1][0];
        if (maxCards == 9) {
          sums1[0] = sums[9]+cardSums[1][1];
        }
      }

      if (nrCards == 2 || nrCards == 3) {
        for (int j=2; j <= maxCards; j++) {
          sums2[j] = sums[j-2]+cardSums[2][0];
          if (maxCards >= 8) {
            sums2[0] = sums[8]+cardSums[2][1];
          }
          if (maxCards == 9) {
            sums2[1] = sums[9]+cardSums[2][1];
          }
        }
      }

      if (nrCards == 3) {
        for (int j=3; j <= maxCards; j++) {
          sums3[j] = sums[j-3]+cardSums[3][0];
          if (maxCards >= 7) {
            sums3[0] = sums[7]+cardSums[3][1];
          }
          if (maxCards >= 8) {
            sums3[1] = sums[8]+cardSums[3][1];
          }
          if (maxCards == 9) {
            sums3[2] = sums[9]+cardSums[3][1];
          }
        }
      }

      for (int j = 0; j <= 9; j++) {
        long largestS = Math.max(sums1[j], sums2[j]);
        largestS = Math.max(largestS, sums3[j]);
        sums[j] = largestS;
      }
    }

    // if (n == 200000) showIntegerArray(sums);

    long largest = sums[0];
    for (int i = 1; i <= 9; i++) {
      largest = Math.max(largest, sums[i]);
    }

    System.out.println(largest);

  } // end of solve

  void insertCard(List<Long> oneCards, long damage) {
    if (oneCards.size() == 3 && damage <= oneCards.get(0)) {
      return;
    }
    if (oneCards.size() == 3) {
      oneCards.remove(0);
    }

    int index = 0;
    while (index < oneCards.size() && damage > oneCards.get(index)) {
      ++index;
    }
    oneCards.add(index, damage);
  }

  long biggest(List<Long> oneCards) {
    if (oneCards.size() == 0) {
      return -1;
    }
    return oneCards.get(oneCards.size()-1);
  }

  long secBiggest(List<Long> oneCards) {
    if (oneCards.size() < 2) {
      return -1;
    }
    return oneCards.get(oneCards.size()-2);
  }

  public static void showIntegerArray(long[] a) {
    for (long l : a) {
      System.out.println(l);
    }
  }

}


import java.io.*;
import java.util.*;

public class A {
	static PrintWriter out;
	static StringBuilder sb;
	static long mod = 1000000007;
	static int inf = 1000000000;
	static long[] fac;
	static int[] si;
	static int n, k;
	static long[][] memo;
	static long[][] a;

	public static void main(String[] args) throws IOException {
		Scanner sc = new Scanner(System.in);
		out = new PrintWriter(System.out);
		n = sc.nextInt();
		memo = new long[n + 1][11];
		a = new long[n][6];
		for (int i = 0; i < n; i++) {
			k = sc.nextInt();
			PriorityQueue<Long> pq = new PriorityQueue<>();
			long two = 0;
			long three = 0;
			for (int j = 0; j < k; j++) {
				int x = sc.nextInt();
				if (x == 2)
					two = Math.max(two, sc.nextInt());
				else if (x == 3)
					three = Math.max(three, sc.nextInt());
				else
					pq.add(sc.nextLong());
				if (pq.size() > 3)
					pq.remove();
			}
			a[i][4] = three;
			a[i][3] = two;
			if (!pq.isEmpty())
				a[i][0] = pq.remove();
			if (!pq.isEmpty())
				a[i][1] = pq.remove();
			if (!pq.isEmpty())
				a[i][2] = pq.remove();
		}
		for (long[] h : memo)
			Arrays.fill(h, -1);
		for(int id=n;id>=0;id--)
			for(int m=10;m>=0;m--)
				dp(id,m);
		out.println(dp(0, 0));
		out.flush();
	}

	static long dp(int i, int m) {
		if (i == n)
			return 0;
		if (memo[i][m] != -1l)
			return memo[i][m];
		long ans = 0;
		Long[] ma = new Long[3];
		for (int id = 0; id < 5; id++) {
			if (id < 3) {
				ma[id] = a[i][id];
			}
		}
		Arrays.sort(ma);
		ans = Math.max(ans, dp(i + 1, (m) % 10));
		if (m == 9) {
			ans = Math.max(ans, 2 * a[i][4] + dp(i + 1, (m + 1) % 10));
			ans = Math.max(ans, 2 * a[i][3] + dp(i + 1, (m + 1) % 10));
			ans = Math.max(ans, 2 * ma[2] + dp(i + 1, (m + 1) % 10));
			if (ma[2] != 0 && a[i][3] != 0)
				ans = Math.max(ans, 2 * Math.max(ma[2], a[i][3]) + Math.min(ma[2], a[i][3]) + dp(i + 1, (m + 2) % 10));
			if (ma[2] != 0 && ma[1] != 0)
				ans = Math.max(ans, 2 * ma[2] + ma[1] + dp(i + 1, (m + 2) % 10));
			if (ma[2] != 0 && ma[1] != 0 && ma[0] != 0)
				ans = Math.max(ans, 2 * ma[2] + ma[1] + ma[0] + dp(i + 1, (m + 3) % 10));
		} else if (m == 8) {
			ans = Math.max(ans, a[i][4] + dp(i + 1, (m + 1) % 10));
			ans = Math.max(ans, a[i][3] + dp(i + 1, (m + 1) % 10));
			ans = Math.max(ans, ma[2] + dp(i + 1, (m + 1) % 10));
			if (ma[2] != 0 && a[i][3] != 0)
				ans = Math.max(ans, 2 * Math.max(ma[2], a[i][3]) + Math.min(ma[2], a[i][3]) + dp(i + 1, (m + 2) % 10));
			if (ma[2] != 0 && ma[1] != 0)
				ans = Math.max(ans, 2 * ma[2] + ma[1] + dp(i + 1, (m + 2) % 10));
			if (ma[2] != 0 && ma[1] != 0 && ma[0] != 0)
				ans = Math.max(ans, 2 * ma[2] + ma[1] + ma[0] + dp(i + 1, (m + 3) % 10));
		} else if (m == 7) {
			ans = Math.max(ans, a[i][4] + dp(i + 1, (m + 1) % 10));
			ans = Math.max(ans, a[i][3] + dp(i + 1, (m + 1) % 10));
			ans = Math.max(ans, ma[2] + dp(i + 1, (m + 1) % 10));
			if (ma[2] != 0 && a[i][3] != 0)
				ans = Math.max(ans, Math.max(ma[2], a[i][3]) + Math.min(ma[2], a[i][3]) + dp(i + 1, (m + 2) % 10));
			if (ma[2] != 0 && ma[1] != 0)
				ans = Math.max(ans, ma[2] + ma[1] + dp(i + 1, (m + 2) % 10));
			if (ma[2] != 0 && ma[1] != 0 && ma[0] != 0)
				ans = Math.max(ans, 2 * ma[2] + ma[1] + ma[0] + dp(i + 1, (m + 3) % 10));
		} else {
			ans = Math.max(ans, a[i][4] + dp(i + 1, (m + 1) % 10));
			ans = Math.max(ans, a[i][3] + dp(i + 1, (m + 1) % 10));
			ans = Math.max(ans, ma[2] + dp(i + 1, (m + 1) % 10));
			if (ma[2] != 0 && a[i][3] != 0)
				ans = Math.max(ans, Math.max(ma[2], a[i][3]) + Math.min(ma[2], a[i][3]) + dp(i + 1, (m + 2) % 10));
			if (ma[2] != 0 && ma[1] != 0)
				ans = Math.max(ans, ma[2] + ma[1] + dp(i + 1, (m + 2) % 10));
			if (ma[2] != 0 && ma[1] != 0 && ma[0] != 0)
				ans = Math.max(ans, ma[2] + ma[1] + ma[0] + dp(i + 1, (m + 3) % 10));
		}
		return memo[i][m] = ans;
	}

	static class pair implements Comparable<pair> {
		int x;
		int y;

		pair(int x, int y) {
			this.x = x;
			this.y = y;
		}

		public String toString() {
			return x + " " + y;
		}

		public int compareTo(pair o) {
			return y - o.y;
		}
	}

	static long inver(long x) {
		int a = (int) x;
		long e = (mod - 2);
		long res = 1;
		while (e > 0) {
			if ((e & 1) == 1) {
				// System.out.println(res*a);
				res = (int) ((1l * res * a) % mod);
			}
			a = (int) ((1l * a * a) % mod);
			e >>= 1;
		}
		// out.println(res+" "+x);
		return res % mod;
	}

	static long fac(int n) {
		if (n == 0)
			return fac[n] = 1;
		if (n == 1)
			return fac[n] = 1;
		long ans = 1;
		for (int i = 1; i <= n; i++)
			fac[i] = ans = (i % mod * ans % mod) % mod;
		return ans % mod;
	}

	static long gcd(long a, long b) {

		if (b == 0)
			return a;
		return gcd(b, a % b);
	}

	static class sol {
		boolean st;
		int l;
		int r;
		char s;

		sol(boolean st, int l, int r, char s) {
			this.st = st;
			this.l = l;
			this.r = r;
			this.s = s;
		}

		public String toString() {
			return st + " " + l + " " + r + " " + s;
		}
	}

	static class unionfind {
		int[] p;
		int[] size;

		unionfind(int n) {
			p = new int[n];
			size = new int[n];

			for (int i = 0; i < n; i++) {
				p[i] = i;
			}
			Arrays.fill(size, 1);
		}

		int findSet(int v) {
			if (v == p[v])
				return v;
			return p[v] = findSet(p[v]);
		}

		boolean sameSet(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return true;
			return false;
		}

		int max() {
			int max = 0;
			for (int i = 0; i < size.length; i++)
				if (size[i] > max)
					max = size[i];
			return max;
		}

		void combine(int a, int b) {
			a = findSet(a);
			b = findSet(b);
			if (a == b)
				return;
			if (size[a] > size[b]) {
				p[b] = a;
				size[a] += size[b];

			} else {
				p[a] = b;
				size[b] += size[a];
			}
		}
	}

	static class Scanner {
		StringTokenizer st;
		BufferedReader br;

		public Scanner(InputStream system) {
			br = new BufferedReader(new InputStreamReader(system));
		}

		public Scanner(String file) throws Exception {
			br = new BufferedReader(new FileReader(file));
		}

		public String next() throws IOException {
			while (st == null || !st.hasMoreTokens())
				st = new StringTokenizer(br.readLine());
			return st.nextToken();
		}

		public String nextLine() throws IOException {
			return br.readLine();
		}

		public int nextInt() throws IOException {
			return Integer.parseInt(next());
		}

		public double nextDouble() throws IOException {
			return Double.parseDouble(next());
		}

		public char nextChar() throws IOException {
			return next().charAt(0);
		}

		public Long nextLong() throws IOException {
			return Long.parseLong(next());
		}

		public boolean ready() throws IOException {
			return br.ready();
		}

		public void waitForInput() throws InterruptedException {
			Thread.sleep(3000);
		}
	}
}


import java.io.*;
import java.util.*;

public class l{
    static class pair implements Comparable<pair>{
        int num,val;
        pair(int a ,int b){
            num=a;
            val=b;
        }

        @Override
        public int compareTo(pair pair) {
            return pair.val-val;
        }
        public String toString(){
            return num+" "+val;
        }
    }
    static long[][]memo;
    static PriorityQueue<Integer>[][]in;
    static int n;
    static long dp(int taken,int id){
        if (id==n)return 0;
        if (memo[taken][id]!=-1)return memo[taken][id];
        long sum=0;
        int max=0;
        int tt=0;
        if (!in[3][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[3][id].peek()+dp(tt,id+1));
            }
            else {
                sum=Math.max(sum,in[3][id].peek()+dp(tt,id+1));
            }
        }
        if (!in[2][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[2][id].peek()+dp(tt,id+1));
            }
            else {
                sum=Math.max(sum,in[2][id].peek()+dp(tt,id+1));
            }
            if (!in[1][id].isEmpty()){
                tt=(2+taken)%10;
                if (taken>tt){
                    sum=Math.max(sum,1l*Math.max(in[1][id].peek(),in[2][id].peek())+in[1][id].peek()+in[2][id].peek()+dp(tt,id+1));
                }
                else {
                    sum=Math.max(sum,in[1][id].peek()+in[2][id].peek()+dp(tt,id+1));
                }
            }
        }
        if (!in[1][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[1][id].peek()+dp(tt,id+1));
            }
            else {
                sum=Math.max(sum,in[1][id].peek()+dp(tt,id+1));
            }
            int x1=in[1][id].poll();
            int x2=0;
            int x3=0;
            if (!in[1][id].isEmpty()){
                x2=in[1][id].poll();
            }
            if (!in[1][id].isEmpty()){
                x3=in[1][id].poll();
            }
            if (x3!=0){
                tt=(taken+3)%10;
                if (taken>tt){
                    sum=Math.max(sum,x1+dp(tt,id+1)+x1+x2+x3);
                }
                else {
                    sum=Math.max(sum,dp(tt,id+1)+x1+x2+x3);
                }
                in[1][id].add(x3);
            }
            if (x2!=0){
                tt=(taken+2)%10;
                if (taken>tt){
                    sum=Math.max(sum,x1+dp(tt,id+1)+x1+x2);
                }
                else {
                    sum=Math.max(sum,dp(tt,id+1)+x1+x2);
                }
                in[1][id].add(x2);
            }
            in[1][id].add(x1);
        }
        sum=Math.max(sum,dp(taken,id+1));
        return memo[taken][id]=sum;
    }
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = sc.nextInt();
        in = new PriorityQueue[4][n];
        for (PriorityQueue[]a:in){
            for (int i =0;i<a.length;i++){
                a[i]= new PriorityQueue(Collections.reverseOrder());
            }
        }
        for (int i =0;i<n;i++){
            int k = sc.nextInt();
            while (k-->0){
                in[sc.nextInt()][i].add(sc.nextInt());
            }
        }
        memo= new long[11][n+10];
        for (long[]x:memo){
            Arrays.fill(x,-1);
        }
        pw.println(dp(0,0));
        //  pw.println(Arrays.deepToString(memo));
        pw.flush();
    }

    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;
        public Scanner(FileReader r){
            br= new BufferedReader(r);
        }
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

        public String next() throws IOException
        {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {return Integer.parseInt(next());}

        public long nextLong() throws IOException {return Long.parseLong(next());}

        public String nextLine() throws IOException {return br.readLine();}

        public double nextDouble() throws IOException
        {
            String x = next();
            StringBuilder sb = new StringBuilder("0");
            double res = 0, f = 1;
            boolean dec = false, neg = false;
            int start = 0;
            if(x.charAt(0) == '-')
            {
                neg = true;
                start++;
            }
            for(int i = start; i < x.length(); i++)
                if(x.charAt(i) == '.')
                {
                    res = Long.parseLong(sb.toString());
                    sb = new StringBuilder("0");
                    dec = true;
                }
                else
                {
                    sb.append(x.charAt(i));
                    if(dec)
                        f *= 10;
                }
            res += Long.parseLong(sb.toString()) / f;
            return res * (neg?-1:1);
        }

        public boolean ready() throws IOException {return br.ready();}

    }
}


import java.io.*;
import java.util.*;

public class l{
    static class pair implements Comparable<pair>{
        int num,val;
        pair(int a ,int b){
            num=a;
            val=b;
        }

        @Override
        public int compareTo(pair pair) {
            return pair.val-val;
        }
        public String toString(){
            return num+" "+val;
        }
    }
    static long[][]memo;
    static PriorityQueue<Integer>[][]in;
    static int n;
    static long dp(int taken,int id){
        if (id==n)return 0l;
        if (memo[taken][id]!=-1)return memo[taken][id];
        long sum=0;
        int tt=0;
        int x1=Math.max(in[1][id].peek(),Math.max(in[2][id].peek(),in[3][id].peek()));
        if (x1!=0) {
            tt = (1 + taken) % 10;
            if (taken > tt) {
                sum = Math.max(sum, 2l * x1 + dp(tt, id + 1));
            } else {
                sum = Math.max(sum, x1 + dp(tt, id + 1));
            }
        }
        x1=in[1][id].poll();
        if (x1!=0) {
            int x2 = in[1][id].poll();
            int m = 0;
            int g = x1;
            if (x2 != 0) {
                m = x1 + x2;
                g = Math.max(x1, x2);
            }
            in[1][id].add(x2);
            x2 = in[2][id].poll();
            if (x2 != 0) {
                m = Math.max(x1 + x2, m);
                g = Math.max(x1, x2);
            }
            in[2][id].add(x2);
            if (m != 0) {
                tt = (2 + taken) % 10;
                if (taken > tt) {
                    sum = Math.max(sum, 1l * g + dp(tt, id + 1) + m);
                } else {
                    sum = Math.max(sum, m + dp(tt, id + 1));
                }
            }
        }
        int x2=in[1][id].poll();
        int x3=in[1][id].poll();
        if (x1!=0&&x2!=0&&x3!=0){
            tt = (3 + taken) % 10;
            if (taken > tt) {
                sum = Math.max(sum, 2l * x1+ x2+x3+ dp(tt, id + 1));
            } else {
                sum = Math.max(sum, 1l*x1+x2+x3+dp(tt, id + 1));
            }
        }
        in[1][id].add(x1);
        in[1][id].add(x2);
        in[1][id].add(x3);
        sum=Math.max(sum,dp(taken,id+1));
        return memo[taken][id]=sum;
    }
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = sc.nextInt();
        in = new PriorityQueue[4][n];
        for (PriorityQueue[]a:in){
            for (int i =0;i<a.length;i++){
                a[i]= new PriorityQueue(Collections.reverseOrder());
                a[i].add(0);
                a[i].add(0);
                a[i].add(0);
            }
        }
        for (int i =0;i<n;i++){
            int k = sc.nextInt();
            while (k-->0){
                in[sc.nextInt()][i].add(sc.nextInt());
            }
        }
        memo= new long[11][n+10];
        for (long[]x:memo){
            Arrays.fill(x,-1);
        }
        pw.println(dp(0,0));
      //  pw.println(Arrays.deepToString(memo));
        pw.flush();
    }

    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;
        public Scanner(FileReader r){
            br= new BufferedReader(r);
        }
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

        public String next() throws IOException
        {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {return Integer.parseInt(next());}

        public long nextLong() throws IOException {return Long.parseLong(next());}

        public String nextLine() throws IOException {return br.readLine();}

        public double nextDouble() throws IOException
        {
            String x = next();
            StringBuilder sb = new StringBuilder("0");
            double res = 0, f = 1;
            boolean dec = false, neg = false;
            int start = 0;
            if(x.charAt(0) == '-')
            {
                neg = true;
                start++;
            }
            for(int i = start; i < x.length(); i++)
                if(x.charAt(i) == '.')
                {
                    res = Long.parseLong(sb.toString());
                    sb = new StringBuilder("0");
                    dec = true;
                }
                else
                {
                    sb.append(x.charAt(i));
                    if(dec)
                        f *= 10;
                }
            res += Long.parseLong(sb.toString()) / f;
            return res * (neg?-1:1);
        }

        public boolean ready() throws IOException {return br.ready();}

    }
}


import java.io.*;
import java.util.*;

public class l{
    static class pair implements Comparable<pair>{
        int num,val;
        pair(int a ,int b){
            num=a;
            val=b;
        }

        @Override
        public int compareTo(pair pair) {
            return pair.val-val;
        }
        public String toString(){
            return num+" "+val;
        }
    }
    static long[][]memo;
    static PriorityQueue<Integer>[][]in;
    static int n;
    static long dp(int taken,int id){
        if (id==n)return 0;
        if (memo[taken][id]!=-1)return memo[taken][id];
        long sum=0;
        int tt=0;
        int x1=Math.max(in[1][id].peek(),Math.max(in[2][id].peek(),in[3][id].peek()));
        if (x1!=0) {
            tt = (1 + taken) % 10;
            if (taken > tt) {
                sum = Math.max(sum, 2l * x1 + dp(tt, id + 1));
            } else {
                sum = Math.max(sum, x1 + dp(tt, id + 1));
            }
        }
        x1=in[1][id].poll();
        if (x1!=0) {
            int x2 = in[1][id].poll();
            int m = 0;
            int g = x1;
            if (x2 != 0) {
                m = x1 + x2;
                g = Math.max(x1, x2);
            }
            in[1][id].add(x2);
            x2 = in[2][id].poll();
            if (x2 != 0) {
                m = Math.max(x1 + x2, m);
                g = Math.max(x1, x2);
            }
            in[2][id].add(x2);
            if (m != 0) {
                tt = (2 + taken) % 10;
                if (taken > tt) {
                    sum = Math.max(sum, 1l * g + dp(tt, id + 1) + m);
                } else {
                    sum = Math.max(sum, m + dp(tt, id + 1));
                }
            }
        }
        int x2=in[1][id].poll();
        int x3=in[1][id].poll();
        if (x1!=0&&x2!=0&&x3!=0){
            tt = (3 + taken) % 10;
            if (taken > tt) {
                sum = Math.max(sum, 2l * x1+ x2+x3+ dp(tt, id + 1));
            } else {
                sum = Math.max(sum, x1+x2+x3+dp(tt, id + 1));
            }
        }
        in[1][id].add(x1);
        in[1][id].add(x2);
        in[1][id].add(x3);
        return memo[taken][id]=sum;
    }
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = sc.nextInt();
        in = new PriorityQueue[4][n];
        for (PriorityQueue[]a:in){
            for (int i =0;i<a.length;i++){
                a[i]= new PriorityQueue(Collections.reverseOrder());
                a[i].add(0);
                a[i].add(0);
                a[i].add(0);
            }
        }
        for (int i =0;i<n;i++){
            int k = sc.nextInt();
            while (k-->0){
                in[sc.nextInt()][i].add(sc.nextInt());
            }
        }
        memo= new long[11][n+10];
        for (long[]x:memo){
            Arrays.fill(x,-1);
        }
        pw.println(dp(0,0));
      //  pw.println(Arrays.deepToString(memo));
        pw.flush();
    }

    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;
        public Scanner(FileReader r){
            br= new BufferedReader(r);
        }
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

        public String next() throws IOException
        {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {return Integer.parseInt(next());}

        public long nextLong() throws IOException {return Long.parseLong(next());}

        public String nextLine() throws IOException {return br.readLine();}

        public double nextDouble() throws IOException
        {
            String x = next();
            StringBuilder sb = new StringBuilder("0");
            double res = 0, f = 1;
            boolean dec = false, neg = false;
            int start = 0;
            if(x.charAt(0) == '-')
            {
                neg = true;
                start++;
            }
            for(int i = start; i < x.length(); i++)
                if(x.charAt(i) == '.')
                {
                    res = Long.parseLong(sb.toString());
                    sb = new StringBuilder("0");
                    dec = true;
                }
                else
                {
                    sb.append(x.charAt(i));
                    if(dec)
                        f *= 10;
                }
            res += Long.parseLong(sb.toString()) / f;
            return res * (neg?-1:1);
        }

        public boolean ready() throws IOException {return br.ready();}

    }
}


import java.io.*;
import java.util.*;

public class l{
    static class pair implements Comparable<pair>{
        int num,val;
        pair(int a ,int b){
            num=a;
            val=b;
        }

        @Override
        public int compareTo(pair pair) {
            return pair.val-val;
        }
        public String toString(){
            return num+" "+val;
        }
    }
    static long[][]memo;
    static PriorityQueue<Integer>[][]in;
    static int n;
    static long dp(int taken,int id){
        if (id==n)return 0;
        if (memo[taken][id]!=-1)return memo[taken][id];
        long sum=0;
        int max=0;
        int tt=0;
        if (!in[3][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[3][id].peek()+dp(tt,id+1));
            }
            else {
                sum=Math.max(sum,in[3][id].peek()+dp(tt,id+1));
            }
        }
        if (!in[2][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[2][id].peek()+dp(tt,id+1));
            }
            else {
                sum=Math.max(sum,in[2][id].peek()+dp(tt,id+1));
            }
            if (!in[1][id].isEmpty()){
                tt=(2+taken)%10;
                if (taken>tt){
                    sum=Math.max(sum,1l*Math.max(in[1][id].peek(),in[2][id].peek())+in[1][id].peek()+in[2][id].peek()+dp(tt,id+1));
                }
                else {
                    sum=Math.max(sum,in[1][id].peek()+in[2][id].peek()+dp(tt,id+1));
                }
            }
        }
        if (!in[1][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[1][id].peek()+dp(tt,id+1));
            }
            else {
                sum=Math.max(sum,in[1][id].peek()+dp(tt,id+1));
            }
            int x1=in[1][id].poll();
            int x2=0;
            int x3=0;
            if (!in[1][id].isEmpty()){
                x2=in[1][id].poll();
            }
            if (!in[1][id].isEmpty()){
                x3=in[1][id].poll();
            }
            if (x3!=0){
                tt=(taken+3)%10;
                if (taken>tt){
                    sum=Math.max(sum,x1+dp(tt,id+1)+x1+x2+x3);
                }
                else {
                    sum=Math.max(sum,dp(tt,id+1)+x1+x2+x3);
                }
                in[1][id].add(x3);
            }
            if (x2!=0){
                tt=(taken+2)%10;
                if (taken>tt){
                    sum=Math.max(sum,x1+dp(tt,id+1)+x1+x2);
                }
                else {
                    sum=Math.max(sum,dp(tt,id+1)+x1+x2);
                }
                in[1][id].add(x2);
            }
            in[1][id].add(x1);
        }
        return memo[taken][id]=sum;
    }
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = sc.nextInt();
        in = new PriorityQueue[4][n];
        for (PriorityQueue[]a:in){
            for (int i =0;i<a.length;i++){
                a[i]= new PriorityQueue(Collections.reverseOrder());
            }
        }
        for (int i =0;i<n;i++){
            int k = sc.nextInt();
            while (k-->0){
                in[sc.nextInt()][i].add(sc.nextInt());
            }
        }
        memo= new long[11][n+10];
        for (long[]x:memo){
            Arrays.fill(x,-1);
        }
        pw.println(dp(0,0));
      //  pw.println(Arrays.deepToString(memo));
        pw.flush();
    }

    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;
        public Scanner(FileReader r){
            br= new BufferedReader(r);
        }
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

        public String next() throws IOException
        {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {return Integer.parseInt(next());}

        public long nextLong() throws IOException {return Long.parseLong(next());}

        public String nextLine() throws IOException {return br.readLine();}

        public double nextDouble() throws IOException
        {
            String x = next();
            StringBuilder sb = new StringBuilder("0");
            double res = 0, f = 1;
            boolean dec = false, neg = false;
            int start = 0;
            if(x.charAt(0) == '-')
            {
                neg = true;
                start++;
            }
            for(int i = start; i < x.length(); i++)
                if(x.charAt(i) == '.')
                {
                    res = Long.parseLong(sb.toString());
                    sb = new StringBuilder("0");
                    dec = true;
                }
                else
                {
                    sb.append(x.charAt(i));
                    if(dec)
                        f *= 10;
                }
            res += Long.parseLong(sb.toString()) / f;
            return res * (neg?-1:1);
        }

        public boolean ready() throws IOException {return br.ready();}

    }
}


import java.io.*;
import java.util.*;

public class l{
    static class pair implements Comparable<pair>{
        int num,val;
        pair(int a ,int b){
            num=a;
            val=b;
        }

        @Override
        public int compareTo(pair pair) {
            return pair.val-val;
        }
        public String toString(){
            return num+" "+val;
        }
    }
    static long[][]memo;
    static PriorityQueue<Integer>[][]in;
    static int n;
    static long dp(int taken,int id){
        if (id==n)return 0l;
        if (memo[taken][id]!=-1)return memo[taken][id];
        long sum=0;
        int tt=0;
        int x1=Math.max(in[1][id].peek(),Math.max(in[2][id].peek(),in[3][id].peek()));
        if (x1!=0) {
            tt = (1 + taken) % 10;
            if (taken > tt) {
                sum = Math.max(sum, 2l * x1 + dp(tt, id + 1));
            } else {
                sum = Math.max(sum, x1 + dp(tt, id + 1));
            }
        }
        x1=in[1][id].poll();
        if (x1!=0) {
            int x2 = in[1][id].poll();
            int m = 0;
            int g = x1;
            if (x2 != 0) {
                m = x1 + x2;
                g = Math.max(x1, x2);
            }
            in[1][id].add(x2);
            x2 = in[2][id].poll();
            if (x2 != 0) {
                m = Math.max(x1 + x2, m);
                g = Math.max(x1, x2);
            }
            in[2][id].add(x2);
            if (m != 0) {
                tt = (2 + taken) % 10;
                if (taken > tt) {
                    sum = Math.max(sum, 1l * g + dp(tt, id + 1) + m);
                } else {
                    sum = Math.max(sum, m + dp(tt, id + 1));
                }
            }
        }
        int x2=in[1][id].poll();
        int x3=in[1][id].poll();
        if (x1!=0&&x2!=0&&x3!=0){
            tt = (3 + taken) % 10;
            if (taken > tt) {
                sum = Math.max(sum, 2l * x1+ x2+x3+ dp(tt, id + 1));
            } else {
                sum = Math.max(sum, x1+x2+x3+dp(tt, id + 1));
            }
        }
        in[1][id].add(x1);
        in[1][id].add(x2);
        in[1][id].add(x3);
        sum=Math.max(sum,dp(taken,id+1));
        return memo[taken][id]=sum;
    }
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = sc.nextInt();
        in = new PriorityQueue[4][n];
        for (PriorityQueue[]a:in){
            for (int i =0;i<a.length;i++){
                a[i]= new PriorityQueue(Collections.reverseOrder());
                a[i].add(0);
                a[i].add(0);
                a[i].add(0);
            }
        }
        for (int i =0;i<n;i++){
            int k = sc.nextInt();
            while (k-->0){
                in[sc.nextInt()][i].add(sc.nextInt());
            }
        }
        memo= new long[11][n+10];
        for (long[]x:memo){
            Arrays.fill(x,-1);
        }
        pw.println(dp(0,0));
      //  pw.println(Arrays.deepToString(memo));
        pw.flush();
    }

    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;
        public Scanner(FileReader r){
            br= new BufferedReader(r);
        }
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

        public String next() throws IOException
        {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {return Integer.parseInt(next());}

        public long nextLong() throws IOException {return Long.parseLong(next());}

        public String nextLine() throws IOException {return br.readLine();}

        public double nextDouble() throws IOException
        {
            String x = next();
            StringBuilder sb = new StringBuilder("0");
            double res = 0, f = 1;
            boolean dec = false, neg = false;
            int start = 0;
            if(x.charAt(0) == '-')
            {
                neg = true;
                start++;
            }
            for(int i = start; i < x.length(); i++)
                if(x.charAt(i) == '.')
                {
                    res = Long.parseLong(sb.toString());
                    sb = new StringBuilder("0");
                    dec = true;
                }
                else
                {
                    sb.append(x.charAt(i));
                    if(dec)
                        f *= 10;
                }
            res += Long.parseLong(sb.toString()) / f;
            return res * (neg?-1:1);
        }

        public boolean ready() throws IOException {return br.ready();}

    }
}


import java.io.*;
import java.util.*;

public class l{
    static class pair implements Comparable<pair>{
        int num,val;
        pair(int a ,int b){
            num=a;
            val=b;
        }

        @Override
        public int compareTo(pair pair) {
            return pair.val-val;
        }
        public String toString(){
            return num+" "+val;
        }
    }
    static long[][][]memo;
    static PriorityQueue<Integer>[][]in;
    static int n;
    static long dp(int pre ,int taken,int id){
        if (id==n)return 0;
        if (memo[pre][taken][id]!=-1)return memo[pre][taken][id];
        long sum=0;
        int max=0;
        int tt=0;
        if (!in[3][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[3][id].peek()+dp(3,tt,id+1));
            }
            else {
                sum=Math.max(sum,in[3][id].peek()+dp(3,tt,id+1));
            }
        }
        if (!in[2][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[2][id].peek()+dp(2,tt,id+1));
            }
            else {
                sum=Math.max(sum,in[2][id].peek()+dp(2,tt,id+1));
            }
            if (!in[1][id].isEmpty()){
                tt=(2+taken)%10;
                if (taken>tt){
                    sum=Math.max(sum,1l*Math.max(in[1][id].peek(),in[2][id].peek())+in[1][id].peek()+in[2][id].peek()+dp(6,tt,id+1));
                }
                else {
                    sum=Math.max(sum,in[1][id].peek()+in[2][id].peek()+dp(6,tt,id+1));
                }
            }
        }
        if (!in[1][id].isEmpty()){
            tt=(1+taken)%10;
            if (taken>tt){
                sum=Math.max(sum,2l*in[1][id].peek()+dp(1,tt,id+1));
            }
            else {
                sum=Math.max(sum,in[1][id].peek()+dp(1,tt,id+1));
            }
            int x1=in[1][id].poll();
            int x2=0;
            int x3=0;
            if (!in[1][id].isEmpty()){
                x2=in[1][id].poll();
            }
            if (!in[1][id].isEmpty()){
                x3=in[1][id].poll();
            }
            if (x3!=0){
                tt=(taken+3)%10;
                if (taken>tt){
                    sum=Math.max(sum,x1+dp(5,tt,id+1)+x1+x2+x3);
                }
                else {
                    sum=Math.max(sum,dp(5,tt,id+1)+x1+x2+x3);
                }
                in[1][id].add(x3);
            }
            if (x2!=0){
                tt=(taken+2)%10;
                if (taken>tt){
                    sum=Math.max(sum,x1+dp(4,tt,id+1)+x1+x2);
                }
                else {
                    sum=Math.max(sum,dp(4,tt,id+1)+x1+x2);
                }
                in[1][id].add(x2);
            }
            in[1][id].add(x1);
        }
        return memo[pre][taken][id]=sum;
    }
    public static void main(String[] args) throws IOException {
        Scanner sc = new Scanner(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        n = sc.nextInt();
        in = new PriorityQueue[4][n];
        for (PriorityQueue[]a:in){
            for (int i =0;i<a.length;i++){
                a[i]= new PriorityQueue(Collections.reverseOrder());
            }
        }
        for (int i =0;i<n;i++){
            int k = sc.nextInt();
            while (k-->0){
                in[sc.nextInt()][i].add(sc.nextInt());
            }
        }
        memo= new long[10][11][n+10];
        for (long[][]x:memo){
            for (long[]a:x)Arrays.fill(a,-1);
        }
        pw.println(dp(0,0,0));
      //  pw.println(Arrays.deepToString(memo));
        pw.flush();
    }

    static class Scanner
    {
        StringTokenizer st;
        BufferedReader br;
        public Scanner(FileReader r){
            br= new BufferedReader(r);
        }
        public Scanner(InputStream s){	br = new BufferedReader(new InputStreamReader(s));}

        public String next() throws IOException
        {
            while (st == null || !st.hasMoreTokens())
                st = new StringTokenizer(br.readLine());
            return st.nextToken();
        }

        public int nextInt() throws IOException {return Integer.parseInt(next());}

        public long nextLong() throws IOException {return Long.parseLong(next());}

        public String nextLine() throws IOException {return br.readLine();}

        public double nextDouble() throws IOException
        {
            String x = next();
            StringBuilder sb = new StringBuilder("0");
            double res = 0, f = 1;
            boolean dec = false, neg = false;
            int start = 0;
            if(x.charAt(0) == '-')
            {
                neg = true;
                start++;
            }
            for(int i = start; i < x.length(); i++)
                if(x.charAt(i) == '.')
                {
                    res = Long.parseLong(sb.toString());
                    sb = new StringBuilder("0");
                    dec = true;
                }
                else
                {
                    sb.append(x.charAt(i));
                    if(dec)
                        f *= 10;
                }
            res += Long.parseLong(sb.toString()) / f;
            return res * (neg?-1:1);
        }

        public boolean ready() throws IOException {return br.ready();}

    }
}