CodeEff/ECCO huggingface dataset:
# Original solution
from itertools import combinations
import sys

N = int(eval(input()))
A = [[] for _ in range(N + 1)]
B = [[] for _ in range(N + 1)]
C = [[] for _ in range(N + 1)]
num_hint = []
# hint_dict = {}
for i in range(1, N + 1):
    num_i = int(eval(input()))
    num_hint.append(num_i)
    for j in range(num_i):
        x, y = list(map(int, input().split()))
        A[i].append((x, y))
        if y == 1:
            B[i].append(x)
        if y == 0:
            C[i].append(x)
        # if hint_dict.get(x) is None:
        #     hint_dict[x] = {0: [], 1: []}
        #     hint_dict[x][y].append(i)
        # else:
        #     hint_dict[x][y].append(i)

for i in range(N + 1, 0, -1):
    for combi in combinations(list(range(1, N + 1)), i):
        remain = set(range(1, N + 1)) - set(combi)
        s = set()
        t = set()
        hint_dict = {}
        for j in combi:
            s |= set(B[j])
            t |= set(C[j])
            for x, y in A[j]:
                if hint_dict.get(x) is None:
                    hint_dict[x] = {0: [], 1: []}
                    hint_dict[x][y].append(i)
                else:
                    hint_dict[x][y].append(i)
        good1 = True
        for value in list(hint_dict.values()):
            if len(value[0]) != 0 and len(value[1]) != 0:
                good1 = False
                break
        good2 = True
        if len(s & remain) != 0:
            good2 = False
        good3 = True
        if len(t & set(combi)) != 0:
            good3 = False
        if good1 and good2 and good3:
            print(i)
            sys.exit()
print((0))


# Optimized solution
N = int(eval(input()))

XY = []
for _ in range(N):
    A = int(eval(input()))
    tmp = []
    for _ in range(A):
        x, y = list(map(int, input().split()))
        tmp.append((x - 1, y))
    XY.append(tmp)


def judge(bit):
    for i in range(N):
        if not (bit & (1 << i)):
            continue
        for x, y in XY[i]:
            if y == 1 and (not (bit & (1 << x))):
                return False
            if y == 0 and (bit & (1 << x)):
                return False
    return True


ans = 0
for bit in range(1 << N):
    if (judge(bit)):
        # print('bit', bit, bin(bit))
        cnt = 0
        for i in range(N):
            if (bit & (1 << i)):
                cnt += 1
        ans = max(ans, cnt)
print(ans)
# Original solution
import re
n=int(eval(input()))
A=[]
for i in range(n):
    B=["."]*n
    for x,y in [list(map(int,input().split())) for k in range(int(eval(input())))]:
        B[x-1]=str(y)
    A.append("".join(B))
ans=0
for i in range(2**n):
    num=format(i,"b").zfill(n)
    cnt,flag=0,1
    for k,j in enumerate(num):
        result=re.search(r"".join(A[k]),num)
        if result!=None and j=="1":
            cnt +=1
        elif (result!=None and j=="0") or (result==None and j=="1"):
            flag=0
            break
    if flag:
        ans=max(ans,cnt)
print(ans)

# Optimized solution
import re
n=int(eval(input()))
A=[]
for i in range(n):
    B=["."]*n
    for x,y in [list(map(int,input().split())) for k in range(int(eval(input())))]:
        B[x-1]=str(y)
    A.append("".join(B))
ans=0
for i in range(2**n):
    num=format(i,"b").zfill(n)
    cnt,flag=0,1
    for k,j in enumerate(num):
        result=re.search(r"".join(A[k]),num)
        if result is not None and j=="1":
            cnt +=1
        elif (result is not None and j == "0") or (result is None and j == "1"):
            flag=0
            break
    if flag:
        ans=max(ans,cnt)
print(ans)
# Original solution
import re
n=int(eval(input()))
A=[]
for i in range(n):
    B=["."]*n
    for x,y in [list(map(int,input().split())) for k in range(int(eval(input())))]:
        B[x-1]=str(y)
    A.append("".join(B))

ans=0
for i in range(2**n):
    num=format(i,"b").zfill(n)
    cnt,flag=0,1
    for k,j in enumerate(num):
        result=re.search(r"".join(A[k]),num)
        if result!=None and j=="1":
            cnt +=1
        elif (result!=None and j=="0") or (result==None and j=="1"):
            flag=0
            break
    if flag:ans=max(ans,cnt)
print(ans)

# Optimized solution
import re
n=int(eval(input()))
A=[]
for i in range(n):
    word=["."]*n
    for j in range(int(eval(input()))):
        x,y=list(map(int,input().split()))
        word[x-1]=str(y)
    A.append(word)

ans=0
for i in range(2**n):
    num=format(i, "b").zfill(n)
    flag,cnt=1,0
    for j,k in enumerate(num):
        search=re.search(r"".join(A[j]),num)
        if search!=None and k=="1":
            cnt +=1
        elif (search==None and k=="1") or (search!=None and k=="0"):
            flag=0
            break
    if flag:ans=max(ans,cnt)
print(ans)
# Original solution
N = int(eval(input()))

state = [[-1] * N for i in range(N)]
for index in range(N):
    Ai = int(eval(input()))
    for naka in range(Ai):
        x, y = list(map(int, input().split())) 
        state[index][x - 1] = y
        # state[index][naka] = [x, y]


# print(state)


maxx = 0
for index in range(2 ** N):
    # print(index)
    person = index
    tempM = 0
    Ai = 0
    ok = 1
    while person > 0:
        if person % 2 == 1:
            tempM += 1
            for i in range(N):
                if state[Ai][i] != -1:
                    # print(str(Ai) + " " + str(i))
                    # print(str(state[Ai][i]) + " " + str((index // (2 ** i)) % 2))
                    # print()
                    if state[Ai][i] != (index // (2 ** i)) % 2:
                        ok = 0
                
        
        person //= 2
        Ai += 1
    
    if ok == 1:
        maxx = max(maxx, tempM)

print(maxx)

# Optimized solution
N = int(eval(input()))

state = [[-1] * N for i in range(N)]
for index in range(N):
    Ai = int(eval(input()))
    for naka in range(Ai):
        x, y = list(map(int, input().split())) 
        state[index][x - 1] = y
        # state[index][naka] = [x, y]


# print(state)


maxx = 0
for index in range(1, 2 ** N):
    # print(index)
    person = index
    tempM = 0
    Ai = 0
    ok = 1
    while person > 0:
        if ok == 0:
            break
        if person % 2 == 1:
            tempM += 1
            for i in range(N):
                if state[Ai][i] != -1:
                    # print(str(Ai) + " " + str(i))
                    # print(str(state[Ai][i]) + " " + str((index // (2 ** i)) % 2))
                    # print()
                    if state[Ai][i] != (index // (2 ** i)) % 2:
                        ok = 0
                        break
                
        
        person //= 2
        Ai += 1
    
    if ok == 1:
        maxx = max(maxx, tempM)

print(maxx)
# Original solution
N = int(eval(input()))
A = [0]*N
X = []
Y = []
for i in range(N):
    A[i] = int(eval(input()))
    X.append([])
    Y.append([])
    for j in range(A[i]):
        x, y = list(map(int, input().split()))
        X[i].append(x-1)
        Y[i].append(y)
ans = 0
for bit in range(1<<N):
    honest = 0
    ok = True
    for i in range(N):
        if bit&(1<<i):
            honest += 1
            for j in range(A[i]):
                if Y[i][j] == 0:
                    if bit&(1<<X[i][j]):
                        ok = False
                        break
                else:
                    if not bit&(1<<X[i][j]):
                        ok = False
                        break
            if not ok:
                break
    if ok:
        ans = max(ans, honest)
print(ans)

# Optimized solution
N = int(eval(input()))
XY = [[] for _ in range(N)]
for i in range(N):
    A = int(eval(input()))
    for _ in range(A):
        x, y = list(map(int, input().split()))
        XY[i].append((x-1,y))
ans = 0
for bit in range(1<<N):
    cnt = bin(bit).count('1')
    ok = True
    for i in range(N):
        if bit&(1<<i):
            for x,y in XY[i]:
                if y == 1:
                    if not bit&(1<<x):
                        ok = False
                        break
                else:
                    if bit&(1<<x):
                        ok = False
                        break
            if not ok:
                break
    if ok:
        ans = max(ans, cnt)
print(ans)
# Original solution
import itertools
n=int(eval(input()))
la=[]
for _ in range(n):
  d=int(eval(input()))
  for dd in range(d):
    x,y=list(map(int,input().split()))
    la.append([_,x-1,y])
ans=0
for i in itertools.product([0,1],repeat=n):
  s=sum(list(i))
  for l in la:
    if i[l[0]]==1 and i[l[1]]!=l[2]:
      break
  else:
    ans=max(ans,s)
print(ans)

# Optimized solution
import itertools
n=int(eval(input()))
l=[]
for i in range(n):
  d=int(eval(input()))
  for dd in range(d):
    x,y=list(map(int,input().split()))
    l.append([i,x-1,y])

ans=0
for p in itertools.product([0,1],repeat=n):
  for ll in l:
    if p[ll[0]]==1 and p[ll[1]]!=ll[2]:
      break
  else:
    ans=max(ans,sum(p))
print(ans)
# Original solution
N=int(eval(input()))
honest=[0 for i in range(N)]
liar=[0 for i in range(N)]
for i in range(N):
  a=int(eval(input()))
  for j in range(a):
    x,y=list(map(int,input().split()))
    if y==0:
      liar[i]|=(1<<(x-1))
    else:
      honest[i]|=(1<<(x-1))

ans=0
for i in range(2**N):
  # 1ループ＝正直者・不親切者の1パターン＝iをビット化したもの
  ok=True
  for j in range(N):
    # j番目が正直者であるパターン
    if (i>>j)&1:
      hon=honest[j]
      pat=i
      while hon>0:
        if hon&1==1 and pat&1==0:
          ok=False
          break
        hon>>=1
        pat>>=1
      li=liar[j]
      pat=i
      while li>0:
        if li&1==1 and pat&1==1:
          ok=False
          break
        li>>=1
        pat>>=1
      if not ok:
        break
  if ok:
    val=i
    cnt=0
    while val>0:
      if val&1==1:
        cnt+=1
      val>>=1
    ans=max(ans,cnt)
        
print(ans)

# Optimized solution
N=int(eval(input()))
honest=[0 for i in range(N)]
liar=[0 for i in range(N)]
for i in range(N):
  a=int(eval(input()))
  for j in range(a):
    x,y=list(map(int,input().split()))
    if y==0:
      liar[i]|=(1<<(x-1))
    else:
      honest[i]|=(1<<(x-1))

ans=0
for i in range(2**N):
  ok=True
  for j in range(N):
    if (i>>j)&1:
      hon=honest[j]
      pat=i
      while hon>0:
        if hon&1==1 and pat&1==0:
          ok=False
          break
        hon>>=1
        pat>>=1
      li=liar[j]
      pat=i
      while li>0:
        if li&1==1 and pat&1==1:
          ok=False
          break
        li>>=1
        pat>>=1
      if not ok:
        break
  if ok:
    val=i
    cnt=0
    while val>0:
      if val&1==1:
        cnt+=1
      val>>=1
    ans=max(ans,cnt)
        
print(ans)
# Original solution
import sys
input = sys.stdin.readline
N, = list(map(int, input().split()))
rs = []
for _ in range(N):
    A, = list(map(int, input().split()))
    ts, fs = set(), set()
    for _ in range(A):
        x, y = list(map(int, input().split()))
        if y:
            ts.add(x-1)
        else:
            fs.add(x-1)
    rs.append((ts, fs))
r = 0
for i in range(2**N):
    i = i+2**N
    bi = bin(i)[3:]
    ok = True
    for j in range(N):
        if int(bi[j]):
            for t in rs[j][0]:
                if not int(bi[t]):
                    ok = False
            for t in rs[j][1]:
                if int(bi[t]):
                    ok = False
    if ok:
        r = max(r, bi.count("1"))
print(r)


# Optimized solution
import sys
input = sys.stdin.readline
N, = list(map(int, input().split()))
rs = []
for _ in range(N):
    A, = list(map(int, input().split()))
    ts, fs = set(), set()
    for _ in range(A):
        x, y = list(map(int, input().split()))
        if y:
            ts.add(x-1)
        else:
            fs.add(x-1)
    rs.append((ts, fs))
r = 0
for i in range(2**N):
    ok = True
    c = 0
    for j in range(N):
        if (i>>j) % 2:
            for t in rs[j][0]:
                if not (i>>t) % 2:
                    ok = False
            for t in rs[j][1]:
                if (i>>t) % 2:
                    ok = False
            c += 1
    if ok:
        r = max(r, c)
print(r)
# Original solution
n=int(eval(input()))
a=[]
x=[]
for _ in range(n):
    A=int(eval(input()))
    X=[list(map(int,input().split())) for _ in range(A)]
    a.append(A)
    x.append(X)
ans=0

for i in range(2**n):
    tmp=[0]*n
    for j in range(n):
        if (i>>j)&1:
            tmp[j]=1
    for k in range(n):
        if a[k]==0:
            continue
        for h in range(a[k]):
            hito=x[k][h][0]-1
            singi=x[k][h][1]
            if tmp[k]==1:
                if tmp[hito]!=singi:
                    break
        else:
            continue
        break
    else:
        ans=max(ans,sum(tmp))

print(ans)




# Optimized solution
n=int(eval(input()))
a=[]
x=[]
for _ in range(n):
    A=int(eval(input()))
    X=[list(map(int,input().split())) for _ in range(A)]
    a.append(A)
    x.append(X)
ans=0

for i in range(2**n):
    tmp=[0]*n
    for j in range(n):
        if (i>>j)&1:
            tmp[j]=1
    for k in range(n):
        # if a[k]==0:
        #     continue
        for h in range(a[k]):
            hito=x[k][h][0]-1
            singi=x[k][h][1]
            if tmp[k]==1:
                if tmp[hito]!=singi:
                    break
        else:
            continue
        break
    else:
        ans=max(ans,sum(tmp))

print(ans)
# Original solution
n = int(eval(input()))

XY = []
for i in range(n):
    a = int(eval(input()))
    xy = []
    for j in range(a):
        xy.append(list(map(int, input().split())))
    
    XY.append(xy)
    
def check(i, xiyj, HoU):
    # 矛盾したらFalse 正直者と仮定した証言より 正直&正直者と仮定されている / 不親切&不親切と仮定されている True
    if ((i >> xiyj) & 1) ^ HoU:
        return False

    return True
    
max_honest = 0
for i in range(2 ** len(XY)):
    count = 0
    is_contradiction = True
    for j in range(len(XY)):
        # 正直者と仮定したときだけ採用
        if not ((i >> j) & 1): continue
        for k in range(len(XY[j])):
            xiyj = XY[j][k][0] - 1
            HoU = XY[j][k][1]
            
            if not check(i, xiyj, HoU):
                is_contradiction = False
                break
                
        if not is_contradiction:
            break

    if is_contradiction:
        for j in range(len(XY)):
            if ((i >> j) & 1): count+=1 
                
        if count > max_honest:
            max_honest =count
            
print(max_honest)

# Optimized solution
n = int(eval(input()))

XY = []
for i in range(n):
    a = int(eval(input()))
    xy = []
    for j in range(a):
        xy.append(list(map(int, input().split())))
    
    XY.append(xy)

"""
    矛盾したらFalse
    矛盾しなければTrue
    正直者と仮定した者の証言
        正直&正直者と仮定されている
        不親切&不親切と仮定されている
"""
def check(i, xiyj, HoU):
    # XOR
    if HoU ^ ((i >> xiyj) & 1):
        return False

    return True

max_honest = 0
for i in range(2 ** len(XY)):
    count = 0
    is_contradiction = True
    for j in range(len(XY)):
        # 正直者と仮定したときだけ採用
        if not ((i >> j) & 1): continue
        count+=1
        for k in range(len(XY[j])):
            xiyj = XY[j][k][0] - 1
            HoU = XY[j][k][1]
            
            if not check(i, xiyj, HoU):
                is_contradiction = False
                break # TLE対策
                
        if not is_contradiction:
            break # TLE対策

    # 矛盾がなく、正直者の数が更新できれば更新
    if is_contradiction and (count > max_honest):
        max_honest =count
            
print(max_honest)
# Original solution
def c_honest_or_unkind_2():
    N = int(eval(input()))
    Answers = []
    for _ in range(N):
        a = int(eval(input()))
        Answers.append([[int(i) for i in input().split()] for j in range(a)])

    # print(Answers)
    ret = -1
    for bits in range(1 << N):
        honests = set()
        unkinds = set()
        for k in range(N):
            if (bits >> k) & 1 == 1:
                honests.add(k)
            else:
                unkinds.add(k)
        # print(honests, unkinds, end=' ')
        is_contradict = False
        for k, answer in enumerate(Answers):
            if k not in honests:
                continue

            for x, y in answer:
                x -= 1
                if (y == 1 and x in unkinds) or (y == 0 and x in honests):
                    # print(k, x, y)
                    is_contradict = True
                    break
            if is_contradict:
                break
        else:
            # print(honests)
            ret = max(ret, len(honests))
    return ret

print((c_honest_or_unkind_2()))

# Optimized solution
def c_honest_or_unkind_2():
    N = int(eval(input()))
    Answers = []
    for _ in range(N):
        a = int(eval(input()))
        Answers.append([[int(i) for i in input().split()] for j in range(a)])

    ret = -1
    for bits in range(1 << N):
        honests = set()
        for k in range(N):
            if (bits >> k) & 1 == 1:
                honests.add(k)

        is_contradict = False
        for k, answer in enumerate(Answers):
            if k not in honests:
                continue  # k 人目は不親切な人としたので証言を調べない

            for x, y in answer:
                x -= 1
                # 証言に矛盾が生じた
                if (y == 0 and x in honests) or (y == 1 and not x in honests):
                    is_contradict = True
                    break
            if is_contradict:
                break  # 1つでも矛盾があれば全証言に矛盾があるとする
        else:
            # 全証言に矛盾がなかったので正直者の人数を更新する
            ret = max(ret, len(honests))
    return ret

print((c_honest_or_unkind_2()))
# Original solution
N = int(eval(input()))
a = [[] for _ in range(N)]
for i in range(N):
  A_i = int(eval(input()))
  for j in range(A_i):
    a[i].append(list(map(int, input().split())))
 
max_honest = 0
for i in range(2**N):
  contradiction = False
  honest_p = []
  unkind_p = []
  doubt_honest_p = []
  doubt_unkind_p = []
  length = len(format(2**N-1, "b"))
  bin_num = format(i, "b").zfill(length)
  for j in range(length):
    if (i >> j) & 1:
      if not j+1 in honest_p:
      	honest_p.append(j+1)
      if not j+1 in doubt_honest_p:
      	doubt_honest_p.append(j+1)
      for k in a[j]:
        p = k[0]
        t = k[1]
        if t:
          if not p in honest_p:
          	honest_p.append(p)
        else:
          if not p in unkind_p: 
          	unkind_p.append(p)
    else:
      if not j+1 in unkind_p:
        unkind_p.append(j+1)
      if not j+1 in doubt_unkind_p:
      	doubt_unkind_p.append(j+1)
  if len(list(set(honest_p) & set(unkind_p))) != 0:
    contradiction = True
  if not contradiction and max_honest <= len(doubt_honest_p):
    max_honest = len(doubt_honest_p)
    
print(max_honest)

# Optimized solution
N = int(eval(input()))
a = [[] for _ in range(N)]
for i in range(N):
  A_i = int(eval(input()))
  for j in range(A_i):
    a[i].append(list(map(int, input().split())))

max_person = 0
for i in range(2**N):
  judge = True
  bin_num = bin(i)
  times = 0
  end = False
  for j in reversed(bin_num):
    if j == "b":
      break
    if j == "1":
      for k in a[times]:
        if ((i >> k[0]-1) & 1) != k[1]:
          judge = False
    times += 1
  true_person = bin_num.count("1")
  if judge == True:
    max_person = max(max_person, true_person)
print(max_person)
# Original solution
import sys
from collections import deque
readline = sys.stdin.readline
N = int(readline())

testimonies = [[[], []] for _ in range(N)]
# testimonies = [[-1 for _ in range(N)] for _ in range(N)]
for i in range(N):
    A = int(readline())
    for _ in range(A):
        x, y = list(map(int, readline().rstrip().split()))
        testimonies[i][y].append(x-1)
        # testimonies[i][x-1] = y

def check(honest_persons):
    """矛盾がないか検証する"""
    honest_checked = set(honest_persons)  # 宛先を確認済みの正直者の人
    honest_stack = deque(honest_persons)  # 宛先を確認する正直者の人の待ち行列
    honest, liers = honest_persons[:], []  # 正直者の人, 不親切な人

    # 正直者の人の証言も元に、正直者の人/不親切な人を追加していく
    while len(honest_stack) > 0:
        honest_person = honest_stack.popleft()
        honest_checked.add(honest_person)
        next_honest_persons = testimonies[honest_person][1]

        # 検証済み以外の人をstackする
        for person in next_honest_persons:
            if person not in honest_checked:
                honest_stack.append(person)

        honest += testimonies[honest_person][1]
        liers += testimonies[honest_person][0]

    # 矛盾がなければOK
    if len(set(honest) & set(liers)) == 0:
        return True
    else:
        return False

def main():
    # bit全探索する
    ans = 0
    has_checked = []
    for i in range(1, 2**N):
        comb = bin(i)[2:].zfill(N)
        honest_persons = [p for p, c in enumerate(comb) if c == '1']
        
        flag = False
        for checked in has_checked:
            if checked < set(honest_persons):
                flag = True
                break
        
        if flag:
            continue

        if check(honest_persons):
            ans = max(ans, sum(list(map(int, list(comb)))))
        else:
            has_checked.append(set(honest_persons))

    print(ans)

if __name__ == '__main__':
    main()

# Optimized solution
import sys
N = int(sys.stdin.readline())

testimonies = [[-1 for _ in range(N)] for _ in range(N)]
for i in range(N):
    A = int(sys.stdin.readline())
    for _ in range(A):
        x, y = list(map(int, sys.stdin.readline().rstrip().split()))
        testimonies[i][x-1] = y

def check(honest_persons):
    flag = True
    for i in range(N):
        if honest_persons[i]:
            for j in range(N):
                if testimonies[i][j] == -1:
                    continue
                if testimonies[i][j] != honest_persons[j]:
                    flag = False
                    break
    return flag

def main():
    ans = 0
    for i in range(1, 2**N):
        honest_persons = bin(i)[2:].zfill(N)
        honest_persons = list(map(int, list(honest_persons)))

        if check(honest_persons):
            ans = max(ans, sum(honest_persons))

    print(ans)

if __name__ == '__main__':
    main()
# Original solution
import sys
N = int(sys.stdin.readline())

testimonies = [[-1 for _ in range(N)] for _ in range(N)]
for i in range(N):
    A = int(sys.stdin.readline())
    for _ in range(A):
        x, y = list(map(int, sys.stdin.readline().rstrip().split()))
        testimonies[i][x-1] = y

def check(honest_persons):
    flag = True
    for i in range(N):
        if honest_persons[i]:
            for j in range(N):
                if testimonies[i][j] == -1:
                    continue
                if testimonies[i][j] != honest_persons[j]:
                    flag = False
                    break
    return flag

def main():
    ans = 0
    for i in range(1, 2**N):
        honest_persons = bin(i)[2:].zfill(N)
        honest_persons = list(map(int, list(honest_persons)))

        if check(honest_persons):
            ans = max(ans, sum(honest_persons))

    print(ans)

if __name__ == '__main__':
    main()

# Optimized solution
import sys
N = int(sys.stdin.readline())

testimonies = [[-1 for _ in range(N)] for _ in range(N)]
for i in range(N):
    A = int(sys.stdin.readline())
    for _ in range(A):
        x, y = list(map(int, sys.stdin.readline().rstrip().split()))
        testimonies[i][x-1] = y

def check(honest_persons):
    flag = True
    for i in range(N):
        if honest_persons[i]:
            for j in range(N):
                if testimonies[i][j] == -1:
                    continue
                if testimonies[i][j] != honest_persons[j]:
                    flag = False
                    break
            else:
                continue
            break
    return flag

def main():
    ans = 0
    for i in range(1, 2**N):
        honest_persons = bin(i)[2:].zfill(N)
        honest_persons = list(map(int, list(honest_persons)))

        if check(honest_persons):
            ans = max(ans, sum(honest_persons))

    print(ans)

if __name__ == '__main__':
    main()