extern crate core;

use std::str::FromStr;
use std::fmt;
use std::cmp::{Ordering, max};
use std::fmt::{Display, Error, Formatter};
use std::ops::{Range, Add};

struct Istream {
    line: Vec<String>,
    position: usize
}
type Parse<T: FromStr> = Result<T, T::Err>;
impl Istream {
    fn new() -> Istream {
        Istream {line:vec![], position: 0}
    }
    fn read_word(&mut self) -> &String {
        if self.position == self.line.len() {
            let mut line= String::new();
            std::io::stdin().read_line(&mut line).ok();
            self.line = line.split_whitespace().map(|x|x.to_string()).collect();
            self.position = 0
        }
        let result = &self.line[self.position];
        self.position += 1;
        result
    }
    fn read(&mut self) -> String {
        self.read_word().to_string()
    }
    fn get<T: FromStr>(&mut self) -> T {self.read_word().parse().ok().unwrap()}
    fn read_usize(&mut self) -> usize {self.get()}
    fn read_int(&mut self) -> i32 {self.get()}
    fn read_long(&mut self) -> i64 {self.get()}
    fn read_double(&mut self) -> f64 {self.get()}
}
macro_rules! read_line{
    () => {{
        let mut line = String::new();
        std::io::stdin().read_line(&mut line).ok();
        line
    }};
    (delimiter: ' ') => {
        read_line!().split_whitespace().map(|x|x.to_string()).collect::<Vec<_>>()
    };
    (delimiter: $p:expr) => {
        read_line!().split($p).map(|x|x.to_string()).collect::<Vec<_>>()
    };
    (' ') => {
        read_line!(delimiter: ' ')
    };
    ($delimiter:expr) => {
        read_line!(delimiter: $delimiter)
    };
    (' '; $ty:ty) => {
        read_line!().split_whitespace().map(|x|x.parse::<$ty>().ok().unwrap()).collect::<Vec<$ty>>()
    };
    ($delimiter:expr; $ty:ty) => {
        read_line!($delimiter).into_iter().map(|x|x.parse::<$ty>().ok().unwrap()).collect::<Vec<$ty>>()
    };
}

macro_rules! let_all {
    ($($n:ident:$t:ty),*) => {
        let line = read_line!(delimiter: ' ');
        let mut iter = line.iter();
        $(let $n:$t = iter.next().unwrap().parse().ok().unwrap();)*
    };
}
macro_rules! repeat {
    ($count:expr; $($statement:tt)+) => {
        for _ in 0 .. $count {
            $($statement)*
        }
    };
}

macro_rules! yields {
    ($count:expr; $block:block) => {{
        let mut vec = Vec::with_capacity($count);
        for _ in 0 .. $count {
            vec.push($block);
        }
        vec
    }}
}
macro_rules! array {
    ($factor: expr; ) => {$factor};
    ($factor: expr; $dimension: expr) => {{
        let size = $dimension;
        let mut vec = Vec::with_capacity(size);
        for _ in 0 .. size {
            vec.push($factor)
        }
        vec
    }};
    ($factor:expr; $dimension:expr, $($r:expr),*) => {{
        let size = $dimension;
        let mut vec = Vec::with_capacity(size);
        for _ in 0 .. size{
            let factor = array!($factor; $($r),*);
            vec.push(factor)
        }
        vec
    }};
}
fn tabulate<F, R>(count: usize, mut generator: F) -> Vec<R> where F : FnMut(usize) -> R {
    let mut result = Vec::<R>::with_capacity(count);
    for f in 0..count {
        result.push(generator(f));
    }
    result
}
#[derive(Copy, Clone, Default)]
struct TimeTable {
    state: usize,
}
impl TimeTable {
    fn new() -> TimeTable {
        TimeTable {state: 0}
    }
    fn add_schedule(&self, from: usize, to: usize) -> TimeTable {
        TimeTable { state: self.state | (((1 << (to - from)) - 1) << (from - 6))}
    }
    fn merged(&self, other: &TimeTable) -> TimeTable {
        TimeTable {state: self.state | other.state}
    }
    fn is_overlap(&self, other: &TimeTable) -> bool {
        self.state & other.state != 0
    }
}

#[derive(Copy, Clone)]
struct Guy {
    time: TimeTable,
    satisfaction: i64,
}
impl Guy {
    fn new() -> Guy {
        Guy{time: TimeTable::new(), satisfaction: 0}
    }
    fn write_schedule(&mut self, from: usize, to: usize) -> () {
        self.time = self.time.add_schedule(from, to);
    }
}
fn solve(guys: &Vec<Guy>, memo: &mut Vec<Vec<i64>>,  used: usize, time: TimeTable) -> i64 {
    if used == guys.len() {
        0
    }else if memo[used][time.state] != -1 {
        memo[used][time.state]
    }else {
        memo[used][time.state] = if guys[used].time.is_overlap(&time) {
            solve(guys, memo, used + 1, time)
        }else {
            max(solve(guys, memo, used + 1, time), solve(guys, memo, used + 1, time.merged(&guys[used].time)) + guys[used].satisfaction)
        };
        memo[used][time.state]
    }
}
fn main() {
    loop {
        let_all!(n: usize);
        if n == 0 {
            break
        }
        let guys: Vec<Guy> = yields!(n; {
            let_all!(m:usize, l:i64);
            let mut guy = Guy::new();
            guy.satisfaction = l;
            for _ in 0 .. m {
                let_all!(s: usize, e: usize);
                guy.write_schedule(s, e);
            }
            guy
        });
        let mut memo: Vec<Vec<i64>> = array!(-1; n, 1 << 16);
        println!("{}", solve(&guys, &mut memo, 0, TimeTable::new()))
    }
}


Measured memory_bytes: 58604