"use strict";
var input = require("fs").readFileSync("/dev/stdin", "utf8");
var cin = input.split(/ |\n/),
    cid = 0;

// number一個取得
// eslint-disable-next-line no-unused-vars
const next = () => +cin[cid++];

// 文字列一個取得
// eslint-disable-next-line no-unused-vars
const nextstr = () => cin[cid++];

// BigInteger一個取得
// eslint-disable-next-line no-unused-vars
const nextbig = () => BigInt(cin[cid++]);

// 長さnの配列として取得。aは文字列フラグ
// eslint-disable-next-line no-unused-vars
const nexts = (n, a) =>
    a ? cin.slice(cid, (cid += n)) : cin.slice(cid, (cid += n)).map((a) => +a);

// w個ずつを組にして長さhの配列。aは文字列フラグ。
// eslint-disable-next-line no-unused-vars
const nextm = (h, w, a) => {
    var r = [],
        i = 0;
    if (a) for (; i < h; i++) r.push(cin.slice(cid, (cid += w)));
    else for (; i < h; i++) r.push(cin.slice(cid, (cid += w)).map((a) => +a));
    return r;
};
// 多次元配列。v,a1,a2,a3 なら、3次元。[[値vで長さa3の配列]をa2個並べた配列]をa1個並べた配列。
// eslint-disable-next-line no-unused-vars
const xArray = (...args) => {
    var a = args,
        l = a.length,
        r = "Array(a[" + --l + "]).fill().map(x=>{return " + a[0] + ";})";
    while (--l) r = "Array(a[" + l + "]).fill().map(x=>" + r + ")";
    return eval(r);
};

console.log(main().toString());

function main() {
    let N = next();
    let A = xArray(0, N);
    let S = xArray(-1, N - 1, 2);
    for (let i = 0; i < N; i++) {
        A[i] = next();
        S[i] = nextm(A[i], 2).map((v) => [v[0] - 1, v[1]]);
    }

    let ans = 0;
    let pat_bits = Array(N);
    for (let pat = 2 ** N - 1; pat > 0; pat--) {
        // nビット目を対応させることに等しい。
        for (let n = 0; n < N; n++) {
            pat_bits[n] = (pat >> n) % 2;
        }
        //console.log("test set", pat_bits);

        let flag = true;
        //console.log("Pattern=", pat_bits);
        for (let i = 0; i < N; i++) {
            // 証言者iについて。
            if (pat_bits[i] == 0) {
                // 不親切の証言は聞く必要がない。
                continue;
            }
            if (!flag) {
                continue;
            }
            //console.log(" person:" + i);
            for (let n = 0; n < A[i]; n++) {
                //console.log("  says, " + S[i][n][0] + " is " + S[i][n][1]);
                if (pat_bits[S[i][n][0]] != S[i][n][1]) {
                    // 間違った証言なので、iは不親切。
                    //console.log("  ... wrong");
                    flag = false;
                    break;
                }
                // console.log("  ... YES!");
            }
            //console.log("Value=" + value, "accept!");
        }
        // flagがtrueならば、この組み合わせは成立している。
        if (flag) {
            let honests = 0;
            pat_bits.forEach((h) => {
                honests += h;
            });
            ans = Math.max(ans, honests);
        }
    }
    return ans;
}
