output_description: For each dataset, you should output the maximum number of parties possible.
input_description: The input consists of multiple datasets. Each dataset has the following
  format:
  
  The first line of the input contains 7 non-negative integers _H_ , _W_ , _C_ ,
  _M_ , _N W_, _N C_, and _N M_, each of which is less than or equals to 50. The
  _i_ -th of the following _W_ lines contains the list of heroes who will be
  getting along with the warrior _i_. The list begins with a non-negative
  integer _n i_ , less than or equals to _H_. Then the rest of the line should
  contain ni positive integers, each of which indicates the ID of a hero getting
  along with the warrior _i_.
  
  After these lists, the following _C_ lines contain the lists of warriors
  getting along with the clerics in the same manner. The _j_ -th line contains a
  list of warriors who will be getting along with the cleric _j_. Then the last
  _M_ lines of the input contain the lists of clerics getting along with the
  mages, of course in the same manner. The _k_ -th line contains a list of
  clerics who will be getting along with the mage _k_.
  
  The last dataset is followed by a line containing seven negative integers.
  This line is not a part of any dataset and should not be processed.
attempt: import collections
  
  
  class MaxFlow:
      """Dinic Algorithm: find max-flow
      complexity: O(EV^2)
      used in GRL6A(AOJ)
      """
  
      class Edge:
          def __init__(self, to, cap, rev):
              self.to, self.cap, self.rev = to, cap, rev
  
      def __init__(self, V):
          """V: the number of vertexes
          E: adjacency list
          source: start point
          sink: goal point
          """
          self.V = V
          self.E = [[] for _ in range(V)]
  
      def add_edge(self, fr, to, cap):
          self.E[fr].append(self.Edge(to, cap, len(self.E[to])))
          self.E[to].append(self.Edge(fr, 0, len(self.E[fr]) - 1))
  
      def run(self, source, sink, INF=10**9):
          """find max-flow"""
          maxflow = 0
          while True:
              self.bfs(source)
              if self.level[sink] < 0:
                  return maxflow
              self.itr = [0] * self.V
              while True:
                  flow = self.dfs(source, sink, INF)
                  if flow > 0:
                      maxflow += flow
                  else:
                      break
  
      def dfs(self, vertex, sink, flow):
          """find augmenting path"""
          if vertex == sink:
              return flow
          for i in range(self.itr[vertex], len(self.E[vertex])):
              self.itr[vertex] = i
              e = self.E[vertex][i]
              if e.cap > 0 and self.level[vertex] < self.level[e.to]:
                  d = self.dfs(e.to, sink, min(flow, e.cap))
                  if d > 0:
                      e.cap -= d
                      self.E[e.to][e.rev].cap += d
                      return d
          return 0
  
      def bfs(self, start):
          """find shortest path from start"""
          que = collections.deque()
          self.level = [-1] * self.V
          que.append(start)
          self.level[start] = 0
  
          while que:
              fr = que.popleft()
              for e in self.E[fr]:
                  if e.cap > 0 and self.level[e.to] < 0:
                      self.level[e.to] = self.level[fr] + 1
                      que.append(e.to)
  
  
  while True:
      row = list(map(int, input().split()))
      H, W, C, M, NW, NC, NM = row
      if H == -1:
          break
      mf = MaxFlow(sum(row) + 2)
      source = sum(row)
      sink = source + 1
  
      toH = lambda i: i
      toW = lambda i: sum(row[:1]) + i
      toC = lambda i: sum(row[:2]) + i
      toM = lambda i: sum(row[:3]) + i
      toNW = lambda i: sum(row[:4]) + i
      toNC = lambda i: sum(row[:5]) + i
      toNM = lambda i: sum(row[:6]) + i
  
      for i in range(H):
          mf.add_edge(source, toH(i), 1)
          for j in range(NW):
              mf.add_edge(toH(i), toNW(j), 1)
  
      for i in range(W):
          _, *friends = map(lambda x: int(x) - 1, input().split())
          for friend in friends:
              mf.add_edge(toH(friend), toW(i), 1)
          for j in range(NC):
              mf.add_edge(toW(i), toNC(j), 1)
  
      for i in range(C):
          _, *friends = map(lambda x: int(x) - 1, input().split())
          for friend in friends:
              mf.add_edge(toW(friend), toC(i), 1)
          for j in range(NW):
              mf.add_edge(toNW(j), toC(i), 1)
          for j in range(NM):
              mf.add_edge(toC(i), toNM(j), 1)
  
      for i in range(M):
          _, *friends = map(lambda x: int(x) - 1, input().split())
          for friend in friends:
              mf.add_edge(toC(friend), toM(i), 1)
          for j in range(NC):
              mf.add_edge(toNC(j), toM(i), 1)
          mf.add_edge(toM(i), sink, 1)
  
      for i in range(NM):
          mf.add_edge(toNC(i), sink, 1)
  
      print(mf.run(source, sink))
  
problem_description: D: Luigi's Tavern
  
  Luigi's Tavern is a thriving tavern in the Kingdom of Nahaila. The owner of
  the tavern Luigi supports to organize a party, because the main customers of
  the tavern are adventurers. Each adventurer has a job: hero, warrior, cleric
  or mage.
  
  Any party should meet the following conditions:
  
    * A party should have a hero.
    * The warrior and the hero in a party should get along with each other.
    * The cleric and the warrior in a party should get along with each other.
    * The mage and the cleric in a party should get along with each other.
    * It is recommended that a party has a warrior, a cleric, and a mage, but it is allowed that at most _N W_, _N C_ and _N m_ parties does not have a warrior, a cleric, and a mage respectively.
    * A party without a cleric should have a warrior and a mage.
  
  Now, the tavern has _H_ heroes, _W_ warriors, _C_ clerics and _M_ mages. Your
  job is to write a program to find the maximum number of parties they can form.
samples: [{"input": "1 1 1 1 1 1\n    1 1\n    1 1\n    1 1\n    1 1 1 1 0 0 0\n    1 1\n    1 1\n    1 1\n    1 0 1 0 1 0 1\n    0\n    1 1 0 1 0 1 0\n    0\n    0\n    1 1 0 1 0 1 0\n    1 1\n    0\n    -1 -1 -1 -1 -1 -1 -1", "output": "1\n    1\n    0\n    1"}]