





"""simple docstring"""






from collections import defaultdict




class 				__lowercase			:







					'''simple docstring'''




					def __init__(						self	,			_UpperCAmelCase	,			_UpperCAmelCase     ):
									__a :						str			       =  total  # total no of tasks (N)

									# DP table will have a dimension of (2^M)*N
									# initially all values are set to -1
									__a :						str			       =  [
									    [-1 for i in range(total + 1     )] for j in range(2 ** len(_UpperCAmelCase     )     )
									]

									__a :						Tuple			       =  defaultdict(_UpperCAmelCase     )  # stores the list of persons for each task

									# final_mask is used to check if all persons are included by setting all bits
									# to 1
									__a :						Dict			       =  (1 << len(_UpperCAmelCase     )) - 1







					def  _lowerCamelCase		(						self	,			_UpperCAmelCase	,			_UpperCAmelCase     ):
									# if mask == self.finalmask all persons are distributed tasks, return 1
									if mask == self.final_mask:
													return 1

									# if not everyone gets the task and no more tasks are available, return 0
									if task_no > self.total_tasks:
													return 0

									# if case already considered
									if self.dp[mask][task_no] != -1:
													return self.dp[mask][task_no]

									# Number of ways when we don't this task in the arrangement
									__a :						Optional[int]			       =  self.count_ways_until(_UpperCAmelCase	,			task_no + 1     )

									# now assign the tasks one by one to all possible persons and recursively
									# assign for the remaining tasks.
									if task_no in self.task:
													for p in self.task[task_no]:
																	# if p is already given a task
																	if mask & (1 << p):
																					continue

																	# assign this task to p and change the mask value. And recursively
																	# assign tasks with the new mask value.
																	total_ways_util += self.count_ways_until(mask | (1 << p)	,			task_no + 1     )

        # save the value.
									__a :						Optional[int]			       =  total_ways_util

									return self.dp[mask][task_no]







					def  _lowerCamelCase		(						self	,			_UpperCAmelCase     ):
									# Store the list of persons for each task
									for i in range(len(_UpperCAmelCase     )     ):
													for j in task_performed[i]:
																	self.task[j].append(_UpperCAmelCase     )

        # call the function to fill the DP table, final answer is stored in dp[0][1]
									return self.count_ways_until(0	,			1     )


if __name__ == "__main__":
		A 			=  5  # total no of tasks (the value of N)

		# the list of tasks that can be done by M persons.
		A 			=  [[1, 3, 4], [1, 2, 5], [3, 4]]
		print(
		    AssignmentUsingBitmask(task_performed, total_tasks).count_no_of_ways(
		        task_performed
		    )
		)






"""simple docstring"""






from __future__ import annotations

from collections import deque
from collections.abc import Iterator
from dataclasses import dataclass




@dataclass
class 				__lowercase			:







					'''simple docstring'''




					__lowerCAmelCase  =  42
					__lowerCAmelCase  =  42






class 				__lowercase			:







					'''simple docstring'''




					def __init__(						self	,			_UpperCAmelCase     ):
									__a :						list[list[Edge]]			       =  [[] for _ in range(_UpperCAmelCase     )]
									__a :						Dict			       =  size







					def __getitem__(						self	,			_UpperCAmelCase     ):
									return iter(self._graph[vertex]     )







					@property
					def  _lowerCamelCase		(						self     ):
									return self._size







					def  _lowerCamelCase		(						self	,			_UpperCAmelCase	,			_UpperCAmelCase	,			_UpperCAmelCase     ):
									if weight not in (0, 1):
													raise ValueError('''Edge weight must be either 0 or 1.'''     )

									if to_vertex < 0 or to_vertex >= self.size:
													raise ValueError('''Vertex indexes must be in [0; size).'''     )

									self._graph[from_vertex].append(Edge(_UpperCAmelCase	,			_UpperCAmelCase     )     )







					def  _lowerCamelCase		(						self	,			_UpperCAmelCase	,			_UpperCAmelCase     ):
									__a :						List[str]			       =  deque([start_vertex]     )
									__a :						list[int | None]			       =  [None] * self.size
									__a :						int			       =  0

									while queue:
													__a :						Any			       =  queue.popleft()
													__a :						Tuple			       =  distances[current_vertex]
													if current_distance is None:
																	continue

													for edge in self[current_vertex]:
																	__a :						List[str]			       =  current_distance + edge.weight
																	__a :						str			       =  distances[edge.destination_vertex]
																	if (
																	    isinstance(_UpperCAmelCase	,			_UpperCAmelCase     )
																	    and new_distance >= dest_vertex_distance
																	):
																					continue
																	__a :						str			       =  new_distance
																	if edge.weight == 0:
																					queue.appendleft(edge.destination_vertex     )
																	else:
																					queue.append(edge.destination_vertex     )

									if distances[finish_vertex] is None:
													raise ValueError('''No path from start_vertex to finish_vertex.'''     )

									return distances[finish_vertex]


if __name__ == "__main__":
		import doctest

		doctest.testmod()