#!/usr/bin/python3 N, M = map(int, input().split()) # Hrany zadaného grafu a hrany obráceného grafu (pro konzistenci se zadáním necháme nultý index prázdný): edges = [[] for _ in range(N+1)] reversed_edges = [[] for _ in range(N+1)] for _ in range(M): u, v = map(int, input().split()) edges[u].append(v) reversed_edges[v].append(u) # Najdeme (správné) komponenty silné souvislosti pomocí algoritmu ze zadání (s normálním DFS): components = [-1 for _ in range(N+1)] # -1 znamená "zatím nevíme" # Průchod obráceným grafem: vertex_stack = [] vertex_seen = [False for _ in range(N+1)] def reverse_dfs(u): vertex_seen[u] = True for v in reversed_edges[u]: if not vertex_seen[v]: reverse_dfs(v) vertex_stack.append(u) for u in range(1, N+1): if not vertex_seen[u]: reverse_dfs(u) # Průchod původním grafem; pořadí určuje zásobník vertex_stack. component_sizes = [0] # Počet vrcholů v jednotlivých komponentách - bude se hodit později def dfs(u, component_name): component_sizes[-1] += 1 components[u] = component_name for v in edges[u]: if components[v] < 0: dfs(v, component_name) component_name = 0 # Průchod v "zásobníkovém" (LIFO) pořadí for u in reversed(vertex_stack): if components[u] < 0: dfs(u, component_name) component_name += 1 component_sizes.append(0) # Máme správně pojmenované komponenty. Teď stačí vypsat řešení: # Algoritmus šarlatána z výprodeje uspěje, když mu vrcholy grafu naservírujeme tak, # aby uzavíral jednu celou komponentu po druhé. print(*sorted(range(1, N+1), key=lambda i: -components[i])) # Abychom zaručili, že algoritmus neuspěje, je to paradoxně pracnější. # Najdeme hranu, která vede mezi komponentami A -> B, přičemž B má alespoň dva vrcholy, a s její pomocí dostaneme chybu algoritmu. def find_ab_edge(): for u in range(1, N+1): for v in edges[u]: if components[u] != components[v] and component_sizes[components[v]] > 1: return [u, v] # Můžete rozmyslet, že taková instance je skutečně neřešitelná - algoritmus na ní nikdy neselže. print("ERROR: Neřešitelná instance.") exit(1) a, b = find_ab_edge() b_comp = components[b] fail_order = [b, a] # Chceme, aby hrana (b, a) v obráceném grafu byla ta první použitá # Potřebujeme jen zaručit, aby ostatní vrcholy komponenty B šly po případných ostatních vrcholech komponenty A. # Vrcholy komponenty B vložíme úplně na konec. for i in range(1, N+1): if i not in [a, b] and components[i] != b_comp: fail_order.append(i) for i in range(1, N+1): if i != b and components[i] == b_comp: fail_order.append(i) print(*fail_order)