Detect a cycle in a directed graph G(V, E) given in the format |V| |E|, followed by source and target nodes for each edge. Output 1 if G has cycle(s), 0 otherwise. Constraints: 1 ≤ |V| ≤ 100, 0 ≤ |E| ≤ 1,000, and source and target nodes for each edge are not equal.

# Buggy version:
from collections import deque, defaultdict

def topological_sort(V, E):
    '''
    Kahn's Algorithm (O(|V| + |E|) time)
    Input:
    V = [0, 1, ..., N-1]: a list of vertices of the digraph
    E: the adjacency list of the digraph (dict)
    Output:
    If the input digraph is acyclic, then return a topological sorting of the digraph.
    Else, return None.
    '''
    indeg = {v: 0 for v in V}
    for ends in E.values():
        for v in ends:
            indeg[v] += 1
    
    q = deque([v for v in V if indeg[v] == 0])
    top_sorted = []
    while q:
        v = q.popleft()
        top_sorted.append(v)
        
        for u in E[v]:
            indeg[u] -= 1
            if indeg[u] == 0:
                q.append(u)
    if len(top_sorted) == len(V): # The input digraph is acyclic.
        return top_sorted
    else: # There is a directed cycle in the digraph.
        return None

N, M = map(int, input().split())
V = range(N)
E = defaultdict(list)
for _ in range(M):
    s, t = map(int, input().split())
    E[s].append(t)
print(0 if topological_sort(V, E) is None else 1)


# Fixed version:
from collections import deque, defaultdict

def topological_sort(V, E):
    '''
    Kahn's Algorithm (O(|V| + |E|) time)
    Input:
    V = [0, 1, ..., N-1]: a list of vertices of the digraph
    E: the adjacency list of the digraph (dict)
    Output:
    If the input digraph is acyclic, then return a topological sorting of the digraph.
    Else, return None.
    '''
    indeg = {v: 0 for v in V}
    for ends in E.values():
        for v in ends:
            indeg[v] += 1
    
    q = deque([v for v in V if indeg[v] == 0])
    top_sorted = []
    while q:
        v = q.popleft()
        top_sorted.append(v)
        
        for u in E[v]:
            indeg[u] -= 1
            if indeg[u] == 0:
                q.append(u)
    if len(top_sorted) == len(V): # The input digraph is acyclic.
        return top_sorted
    else: # There is a directed cycle in the digraph.
        return None

N, M = map(int, input().split())
V = range(N)
E = defaultdict(list)
for _ in range(M):
    s, t = map(int, input().split())
    E[s].append(t)
print(1 if topological_sort(V, E) is None else 0)

# Buggy version:
#Detectando Ciclos en un grafo
#Se puede mejorar a un mas
from collections import deque
import sys

def dfs(G,u):
    n = len(G)
    vis=[-1]*n
    stackV = []
    pila = deque()
    pila.append(u)
    vis[u]=1
    stackV.append(u)
    while(pila):
        w = pila.pop()
        for v in G[w]:
            if(vis[v]==-1):
                vis[v]=1
                pila.append(v)
                stackV.append(v)
            elif(vis[v]==1 and v==u):
                print(stackV)
                return True
    return False

def main():
    G =[]
    val = [int(x) for x in sys.stdin.readline().strip().split()]
    for i in range(val[0]):
        G.append([])
    for i in range(val[1]):
        L = [int(x) for x in sys.stdin.readline().strip().split()]
        G[L[0]].append(L[1]) 
    veri=[]

    for i in range(val[0]):
        veri.append(dfs(G,i))
    print(veri)
    if(True in veri):print(1)
    else:print(0)
        
main()
        



# Fixed version:
#Detectando Ciclos en un grafo
#Se puede mejorar a un mas
from collections import deque
import sys

def dfs(G,u):
    n = len(G)
    vis=[-1]*n
    stackV = []
    pila = deque()
    pila.append(u)
    vis[u]=1
    stackV.append(u)
    while(pila):
        w = pila.pop()
        for v in G[w]:
            if(vis[v]==-1):
                vis[v]=1
                pila.append(v)
                stackV.append(v)
            elif(vis[v]==1 and v==u):
                return True
    return False

def main():
    G =[]
    val = [int(x) for x in sys.stdin.readline().strip().split()]
    for i in range(val[0]):
        G.append([])
    for i in range(val[1]):
        L = [int(x) for x in sys.stdin.readline().strip().split()]
        G[L[0]].append(L[1]) 
    veri=[]

    for i in range(val[0]):
        veri.append(dfs(G,i))
    if(True in veri):print(1)
    else:print(0)
        
main()