```go
package main
import (
"bufio"
"fmt"
"os"
)
type FastReader struct {
r *bufio.Reader
}
func NewFastReader() *FastReader {
return &FastReader{r: bufio.NewReaderSize(os.Stdin, 1<<20)}
}
func (fr *FastReader) nextInt64() int64 {
sign := int64(1)
val := int64(0)
c, err := fr.r.ReadByte()
for (c < '0' || c > '9') && c != '-' {
c, err = fr.r.ReadByte()
if err != nil {
return 0
}
}
if c == '-' {
sign = -1
c, err = fr.r.ReadByte()
if err != nil {
return 0
}
}
for c >= '0' && c <= '9' {
val = val*10 + int64(c-'0')
c, err = fr.r.ReadByte()
if err != nil {
break
}
}
return val * sign
}
func main() {
in := NewFastReader()
out := bufio.NewWriterSize(os.Stdout, 1<<20)
defer out.Flush()
negInf := int64(-1 << 60)
n := int(in.nextInt64())
dp := make([]int64, 10)
for i := 0; i < 10; i++ {
dp[i] = negInf
}
dp[0] = 0
for i := 0; i < n; i++ {
k := int(in.nextInt64())
top1 := [3]int64{negInf, negInf, negInf}
top2 := negInf
top3 := negInf
insertTop3 := func(v int64) {
if v > top1[0] {
top1[2] = top1[1]
top1[1] = top1[0]
top1[0] = v
} else if v > top1[1] {
top1[2] = top1[1]
top1[1] = v
} else if v > top1[2] {
top1[2] = v
}
}
for j := 0; j < k; j++ {
c := int(in.nextInt64())
d := in.nextInt64()
if c == 1 {
insertTop3(d)
} else if c == 2 {
if d > top2 {
top2 = d
}
} else {
if d > top3 {
top3 = d
}
}
}
bestSum := [4]int64{0, negInf, negInf, negInf}
bestPlus := [4]int64{0, negInf, negInf, negInf}
m1 := top1[0]
if top2 > m1 {
m1 = top2
}
if top3 > m1 {
m1 = top3
}
if m1 > negInf/2 {
bestSum[1] = m1
bestPlus[1] = m1 * 2
}
sumA, plusA := negInf, negInf
if top1[1] > negInf/2 {
sumA = top1[0] + top1[1]
plusA = sumA + top1[0]
}
sumB, plusB := negInf, negInf
if top1[0] > negInf/2 && top2 > negInf/2 {
sumB = top1[0] + top2
if top1[0] > top2 {
plusB = sumB + top1[0]
} else {
plusB = sumB + top2
}
}
if sumA > bestSum[2] {
bestSum[2] = sumA
}
if sumB > bestSum[2] {
bestSum[2] = sumB
}
if plusA > bestPlus[2] {
bestPlus[2] = plusA
}
if plusB > bestPlus[2] {
bestPlus[2] = plusB
}
if top1[2] > negInf/2 {
sumC := top1[0] + top1[1] + top1[2]
bestSum[3] = sumC
bestPlus[3] = sumC + top1[0]
}
dpNext := make([]int64, 10)
for r := 0; r < 10; r++ {
dpNext[r] = negInf
}
for r := 0; r < 10; r++ {
if dp[r] <= negInf/2 {
continue
}
for t := 0; t <= 3; t++ {
if bestSum[t] <= negInf/2 {
continue
}
r1 := (r + t) % 10
s := (10 - r) % 10
add := bestSum[t]
if s >= 1 && s <= t {
add = bestPlus[t]
}
val := dp[r] + add
if val > dpNext[r1] {
dpNext[r1] = val
}
}
}
dp = dpNext
}
ans := dp[0]
for i := 1; i < 10; i++ {
if dp[i] > ans {
ans = dp[i]
}
}
fmt.Fprintln(out, ans)
}
```