Problem:
Score : 300 points

Problem Statement

There are N people numbered 1 to N. Each of them is either an honest person whose testimonies are always correct or an unkind person whose testimonies may be correct or not.

Person i gives A_i testimonies. The j-th testimony by Person i is represented by two integers x_{ij} and y_{ij}. If y_{ij} = 1, the testimony says Person x_{ij} is honest; if y_{ij} = 0, it says Person x_{ij} is unkind.

How many honest persons can be among those N people at most?

Constraints

All values in input are integers.

1 \leq N \leq 15

0 \leq A_i \leq N - 1

1 \leq x_{ij} \leq N

x_{ij} \neq i

x_{ij_1} \neq x_{ij_2} (j_1 \neq j_2)

y_{ij} = 0, 1

Input

Input is given from Standard Input in the following format:

N
A_1
x_{11} y_{11}
x_{12} y_{12}
:
x_{1A_1} y_{1A_1}
A_2
x_{21} y_{21}
x_{22} y_{22}
:
x_{2A_2} y_{2A_2}
:
A_N
x_{N1} y_{N1}
x_{N2} y_{N2}
:
x_{NA_N} y_{NA_N}

Output

Print the maximum possible number of honest persons among the N people.

Sample Input 1

3
1
2 1
1
1 1
1
2 0

Sample Output 1

2

If Person 1 and Person 2 are honest and Person 3 is unkind, we have two honest persons without inconsistencies, which is the maximum possible number of honest persons.

Sample Input 2

3
2
2 1
3 0
2
3 1
1 0
2
1 1
2 0

Sample Output 2

0

Assuming that one or more of them are honest immediately leads to a contradiction.

Sample Input 3

2
1
2 0
1
1 0

Sample Output 3

1

Solution in C# (Mono 4.6.2.0) (judge verdict: Wrong Answer)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static void Main(string[] args)
    {
        var waaaa = new waaaa();
        waaaa.Solve();
    }
}

public class waaaa
{
    const int MOD = 1000000007;
    const int INF = 1 << 20;
    const long INFL = 1 << 62;
    const int MOD2 = 998244353;

    myinout IO = new myinout();
    Math2 mmath = new Math2();



    public void Solve()
    {
        //ここから
        var N = IO.Int1;
        int[,] x = new int[N, N];
        int[,] y = new int[N, N];

        for (int i = 0; i < N; ++i)
        {
            for (int j = 0; j < N; ++j)
            {
                x[i, j] = -1;
                y[i, j] = -1;
            }
        }

        for (int i = 0; i < N; ++i)
        {
            int A = IO.Int1;
            for (int j = 0; j < A; ++j)
            {
                var o = IO.IntM;
                x[i, j] = o[0] - 1;
                y[i, j] = o[1];
            }
        }
        int ans = 0;
        for (int i = 0; i < (1 << N); ++i)
        {
            int count = 0;
            bool f = true;
            for (int j = 0; j < N; ++j)
            {
                if (((i >> j) & 1) == 1)
                {
                    count++;

                    bool f2 = true;
                    for (int k = 0; k < N; ++k) //k番目の証人
                    {
                        for (int l = 0; l < N; ++l) //l番目の証言
                        {
                            if (((i >> k) & 1) == 1 && x[k, l] == j && y[k, l] == 0) f2 = false;
                        }
                    }

                    if (!f2)
                    {
                        f = false;
                        break;
                    }


                }
            }
            if (f) ans = Math.Max(ans, count);
        }
        IO.wri(ans);

    }

}

//b-aで降順

public class Math2
{
    public long[] Fact;  //Nまでの階乗
    public long[] invFact;  //階乗の逆元

    //Nまでの階乗をセットしておく
    public void FactoricalModSet(long N, long MOD = 1000000007)
    {
        Fact = new long[N + 1];
        invFact = new long[N + 1];

        Fact[0] = 1;
        for (long i = 1; i <= N; ++i)
        {
            Fact[i] = Fact[i - 1] * i % MOD;
        }
        invFact[N] = pow(Fact[N], MOD - 2);

        for (long i = N; i > 0; --i)
        {
            invFact[i - 1] = invFact[i] * i % MOD;
        }

    }

    //nCr 引数:n r (mod)
    public long nCr(long n, long r, long MOD = 1000000007)
    {
        return (Fact[n] * invFact[r] % MOD * invFact[n - r] % MOD);
    }

    //階乗(O(logN)) 引数:底x n乗　(MOD)
    public long pow(long x, long n, long MOD = 1000000007)
    {
        long res = 1;
        while (n > 0)
        {
            if ((n & 1) != 0) res = res * x % MOD;
            x = x * x % MOD;
            n >>= 1;
        }
        return res;
    }

    //最大公約数 引数:整数x,y
    public long GCD(long x, long y)
    {
        while (y != 0)
        {
            var r = x % y;
            x = y;
            y = r;
        }
        return x;
    }

    //最小公倍数 引数:整数x,y
    public long LCM(long x, long y)
    {
        return x * y / GCD(x, y);
    }

    //素因数分解 引数:整数N
    public Dictionary<long, int> PrimeFactorization(long N)
    {
        var ret = new Dictionary<long, int>();

        for (long i = 2; i * i <= N; ++i)
        {
            int cnt = 0;
            while (N % i == 0)
            {
                cnt++;
                N /= i;
            }
            if (cnt != 0) ret[i] = cnt;

        }
        if (N >= 2) ret[N] = 1;

        return ret;

    }

    //約数列挙
    public List<long> divisorenumrate(long N)
    {
        var ret = new List<long>();

        for (long i = 1; i * i <= N; ++i)
        {

            if (N % i == 0)
            {
                ret.Add(i);
                ret.Add(N / i);
            }

        }

        return ret;

    }

    public void Swap<T>(ref T a, ref T b)
    {
        var x = a;
        a = b;
        b = x;
    }

}

class myinout
{
    //in
    public string Str => Console.ReadLine();

    public string[] StrM => Str.Split(' ');

    public long[] LongM => StrM.Select(long.Parse).ToArray();
    public int[] IntM => StrM.Select(int.Parse).ToArray();
    public char[] CharM => Str.ToArray();
    public long Long1 => LongM[0];
    public int Int1 => IntM[0];

    //out
    public void wri<T>(T x)
    {
        Console.WriteLine(x);
    }

    public void yn(bool x)
    {
        if (x) wri("Yes");
        else wri("No");
    }

}