




'''simple docstring'''
import multiprocessing
import os
from typing import BinaryIO, Optional, Union

from .. import Dataset, Features, NamedSplit, config
from ..formatting import query_table
from ..packaged_modules.csv.csv import Csv
from ..utils import logging
from ..utils.typing import NestedDataStructureLike, PathLike
from .abc import AbstractDatasetReader
class 					__UpperCAmelCase							(    A__							):



					'''simple docstring'''





					def __init__(  self    :	List[Any]			,					_lowercase    :	NestedDataStructureLike[PathLike]			,					_lowercase    :	Optional[NamedSplit] = None			,					_lowercase    :	Optional[Features] = None			,					_lowercase    :	str = None			,					_lowercase    :	bool = False			,					_lowercase    :	bool = False			,					_lowercase    :	Optional[int] = None			,					**_lowercase    :	Union[str, Any]			,					)						->       str:
								super().__init__(
								    _lowercase			,					split=_lowercase			,					features=_lowercase			,					cache_dir=_lowercase			,					keep_in_memory=_lowercase			,					streaming=_lowercase			,					num_proc=_lowercase			,					**_lowercase			,					)
								A_       		=   path_or_paths if isinstance(_lowercase			,					_lowercase) else {self.split: path_or_paths}
								A_       		=   Csv(
								    cache_dir=_lowercase			,					data_files=_lowercase			,					features=_lowercase			,					**_lowercase			,					)



					def 						__snake_case	(  self    :	Optional[int])						->       List[str]:






								if self.streaming:
											A_       		=   self.builder.as_streaming_dataset(split=self.split)
								# Build regular (map-style) dataset
								else:
											A_       		=   None
											A_       		=   None
											A_       		=   None
											A_       		=   None

											self.builder.download_and_prepare(
											    download_config=_lowercase			,					download_mode=_lowercase			,					verification_mode=_lowercase			,					base_path=_lowercase			,					num_proc=self.num_proc			,					)
											A_       		=   self.builder.as_dataset(
											    split=self.split			,					verification_mode=_lowercase			,					in_memory=self.keep_in_memory)
								return dataset





class 					__UpperCAmelCase							:



					'''simple docstring'''





					def __init__(  self    :	List[str]			,					_lowercase    :	Dataset			,					_lowercase    :	Union[PathLike, BinaryIO]			,					_lowercase    :	Optional[int] = None			,					_lowercase    :	Optional[int] = None			,					**_lowercase    :	Optional[Any]			,					)						->       str:






								if num_proc is not None and num_proc <= 0:
											raise ValueError(F'num_proc {num_proc} must be an integer > 0.')

								A_       		=   dataset
								A_       		=   path_or_buf
								A_       		=   batch_size if batch_size else config.DEFAULT_MAX_BATCH_SIZE
								A_       		=   num_proc
								A_       		=   "utf-8"
								A_       		=   to_csv_kwargs



					def 						__snake_case	(  self    :	List[str])						->       Optional[Any]:
								A_       		=   self.to_csv_kwargs.pop('path_or_buf'			,					_lowercase)
								A_       		=   self.to_csv_kwargs.pop('header'			,					_lowercase)
								A_       		=   self.to_csv_kwargs.pop('index'			,					_lowercase)

								if isinstance(self.path_or_buf			,					(str, bytes, os.PathLike)):
											with open(self.path_or_buf			,					'wb+') as buffer:
														A_       		=   self._write(file_obj=_lowercase			,					header=_lowercase			,					index=_lowercase			,					**self.to_csv_kwargs)
								else:
											A_       		=   self._write(file_obj=self.path_or_buf			,					header=_lowercase			,					index=_lowercase			,					**self.to_csv_kwargs)
								return written



					def 						__snake_case	(  self    :	Optional[Any]			,					_lowercase    :	str)						->       Any:
								A_       		=   args

								A_       		=   query_table(
								    table=self.dataset.data			,					key=slice(_lowercase			,					offset + self.batch_size)			,					indices=self.dataset._indices			,					)
								A_       		=   batch.to_pandas().to_csv(
								    path_or_buf=_lowercase			,					header=header if (offset == 0) else False			,					index=_lowercase			,					**_lowercase)
								return csv_str.encode(self.encoding)



					def 						__snake_case	(  self    :	str			,					_lowercase    :	BinaryIO			,					_lowercase    :	List[Any]			,					_lowercase    :	Union[str, Any]			,					**_lowercase    :	List[str])						->       Union[str, Any]:
								A_       		=   0

								if self.num_proc is None or self.num_proc == 1:
											for offset in logging.tqdm(
											    range(0			,					len(self.dataset)			,					self.batch_size)			,					unit='ba'			,					disable=not logging.is_progress_bar_enabled()			,					desc='Creating CSV from Arrow format'			,					):
														A_       		=   self._batch_csv((offset, header, index, to_csv_kwargs))
														written += file_obj.write(_lowercase)

								else:
											A_       		=   len(self.dataset), self.batch_size
											with multiprocessing.Pool(self.num_proc) as pool:
														for csv_str in logging.tqdm(
														    pool.imap(
														        self._batch_csv			,					[(offset, header, index, to_csv_kwargs) for offset in range(0			,					_lowercase			,					_lowercase)]			,					)			,					total=(num_rows // batch_size) + 1 if num_rows % batch_size else num_rows // batch_size			,					unit='ba'			,					disable=not logging.is_progress_bar_enabled()			,					desc='Creating CSV from Arrow format'			,					):
																	written += file_obj.write(_lowercase)

								return written










'''simple docstring'''
from __future__ import annotations





def  lowerCamelCase(       SCREAMING_SNAKE_CASE_    )		->		Optional[int]:
			global graph, reversed_graph, scc, component, visit, stack
			if visit[u]:
						return
			A_       		=   True
			for v in graph[u]:
						dfs(SCREAMING_SNAKE_CASE_    )
			stack.append(SCREAMING_SNAKE_CASE_    )





def  lowerCamelCase(       SCREAMING_SNAKE_CASE_    )		->		List[Any]:
			global graph, reversed_graph, scc, component, visit, stack
			if visit[u]:
						return
			A_       		=   True
			component.append(SCREAMING_SNAKE_CASE_    )
			for v in reversed_graph[u]:
						dfsa(SCREAMING_SNAKE_CASE_    )





def  lowerCamelCase(       )		->		int:
			global graph, reversed_graph, scc, component, visit, stack
			for i in range(SCREAMING_SNAKE_CASE_    ):
						dfs(SCREAMING_SNAKE_CASE_    )
			A_       		=   [False] * n
			for i in stack[::-1]:
						if visit[i]:
									continue
						A_       		=   []
						dfsa(SCREAMING_SNAKE_CASE_    )
						scc.append(SCREAMING_SNAKE_CASE_    )
			return scc


if __name__ == "__main__":
							# n - no of nodes, m - no of edges
							_SCREAMING_SNAKE_CASE ,						_SCREAMING_SNAKE_CASE =	list(map(int, input().strip().split()))

							_SCREAMING_SNAKE_CASE =	[[] for _ in range(n)]  # graph
							_SCREAMING_SNAKE_CASE =	[[] for i in range(n)]  # reversed graph
							# input graph data (edges)
							for _ in range(m):
														_SCREAMING_SNAKE_CASE ,						_SCREAMING_SNAKE_CASE =	list(map(int, input().strip().split()))
														graph[u].append(v)
														reversed_graph[v].append(u)

							_SCREAMING_SNAKE_CASE =	[]
							_SCREAMING_SNAKE_CASE =	[False] * n
							_SCREAMING_SNAKE_CASE =	[]
							_SCREAMING_SNAKE_CASE =	[]
							print(kosaraju())




