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: Accepted)

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

namespace AtCoder2 {
	class Program {
		static void Main(string[] args) {

var inputArray = retreiveLongArray();
			var inputCount = 1;

			// 不正な入力は処理しない
			if (inputArray.Length != inputCount) {
				Console.WriteLine("invalid input");
				return;
			}

			var N = inputArray[0];

			var manList = new List<TestedMan>();

			for (int i = 0; i < N; i++) {
				var newMan = new TestedMan();
				manList.Add(newMan);
			}

			var ans = 0;


			for (int i = 0; i < Math.Pow(2,N); i++) {
				var katei = new bool[N];

				for (int j = 0; j < N; j++) {
					var x 	= (i >> j) & 1;
					katei[j] = (x == 1);

				}

				var result = true;

				for (int k = 0; k < N; k++) {
					var man = manList[k];

					//仮定配列の正直/不親切と証言の判定結果が矛盾しているかどうか
					if (katei[k]!=man.hantei(katei)) {
						result = false;
						break;
					}
				}


				if (result) {
					ans = Math.Max(ans, katei.Count(x => x));
				}

			}

			//答えの出力
			Console.WriteLine(ans);

		}

		/// <summary>
		/// スペースで区切られた文字列配列の入力を受け取る
		/// </summary>
		/// <returns></returns>
		private static string[] retreiveStringArray() {
			var inputArray = Console.ReadLine().Split(' ');
			return inputArray;
		}

		/// <summary>
		/// スペースで区切られた整数配列の入力を受け取る
		/// </summary>
		/// <returns></returns>
		private static long[] retreiveLongArray() {
			var inputArray = Console.ReadLine().Split(' ');
			var longArray = inputArray.Select(s => long.Parse(s));
			return longArray.ToArray();
		}
	}
	public class TestedMan {

		/// <summary>
		/// 何人の証言をするか
		/// </summary>
		public int ninsu { get; set; }

		public Dictionary<int, bool> _shougenDic;

		public TestedMan() {
			_shougenDic = new Dictionary<int, bool>();
			ninsu = (int)retreiveLongArray()[0];

			for (int i = 0; i < ninsu; i++) {

				var shougen = retreiveLongArray();
				var target = (int)shougen[0];
				var result = (int)shougen[1];

				_shougenDic.Add(target,result==1) ;
			}

		}

		/// <summary>
		/// 与えられた正直/不親切の配列と、この人の証言が矛盾しているか確認する
		/// </summary>
		/// <param name="katei"></param>
		/// <returns></returns>
		public bool hantei(bool[] katei) {

			foreach (var shogen in _shougenDic) {
				var i = shogen.Key;
				if (katei[i - 1] != shogen.Value) {
					return false;
				}
			}

			return true;
		}

		/// <summary>
		/// スペースで区切られた整数配列の入力を受け取る
		/// </summary>
		/// <returns></returns>
		private static long[] retreiveLongArray() {
			var inputArray = Console.ReadLine().Split(' ');
			var longArray = inputArray.Select(s => long.Parse(s));
			return longArray.ToArray();
		}
	}
}