{*************************************************************************
 *                                                                       *
 *                       Pogromcy Algorytmów 2004                        *
 *                                                                       *
 *   Rozwiązanie zadania: Bajtocka Agencja Informacyjna                  *
 *   Plik:                bai.pas                                        *
 *   Autor:               Krzysztof Onak                                 *
 *************************************************************************}

(*
 * Zadanie: Bajtocka Agencja Informacyjna
 * Rodzaj programu: rozwiązanie wzorcowe
 * Autor: Krzysztof Onak
 * Algorytm: Program tworzy drzewo DFS o korzeniu w serwerze.
 * 	Następnie analizuje wierzchołki idąc w kolejności odwrotnej
 * 	do kolejności inorder. Ogólnie rzecz mówiąc, nie jest to takie
 * 	proste i zadanie może być kilerskie, chyba że nie znam jakiegoś
 * 	łatwego rozwiązania.
 * Złożoność czasowa: O(n^2)
 * Złożoność pamięciowa: O(n + m)
 *)

const MAXN = 5000;

type
	PList = ^TList;
	TList =
		record
			item : LongInt;
			next : PList;
		end;

type
	ListArray = array[1..MAXN] of PList;
	IntArray = array[1..MAXN] of LongInt;
	BoolArray = array[1..MAXN] of Boolean;

procedure insert(var list : PList; item : LongInt);
var newHead : PList;
begin
	new(newHead);
	newHead^.item := item;
	newHead^.next := list;
	list := newHead;
end;

var
	n : LongInt;
	incoming, outgoing, sons : ListArray;
	preorder, order : IntArray;
	articulation : BoolArray;

procedure readInput;
var m, i, a, b : LongInt;
begin
	read(n, m);
	for i := 1 to n do begin
		incoming[i] := nil;
		outgoing[i] := nil;
	end;
	for i := 1 to m do begin
		read(a, b);
		insert(outgoing[a], b);
		insert(incoming[b], a);
	end;
end;

procedure dfs(v : LongInt; f : LongInt;
	var counter : LongInt; var visited : BoolArray);
var p : PList;
begin
	if visited[v] then exit;
	visited[v] := true;
	inc(counter);
	order[counter] := v;
	preorder[v] := counter;
	if f <> -1 then
		insert(sons[f], v);
	p := outgoing[v];
	while p <> nil do begin
		dfs(p^.item, v, counter, visited);
		p := p^.next;
	end;
end;

procedure createTree;
var
	i, counter : LongInt;
	visited : BoolArray;
begin
	counter := 0;
	for i := 1 to n do begin
		sons[i] := nil;
		visited[i] := false;
	end;
	dfs(1, -1, counter, visited);
end;

procedure propagateAlternativeDown(v, alt : LongInt;
	var alternative : IntArray);
var p : PList;
begin
	if preorder[alt] >= preorder[alternative[v]] then exit;
	alternative[v] := alt;
	p := sons[v];
	while p <> nil do begin
		propagateAlternativeDown(p^.item, alt, alternative);
		p := p^.next;
	end;
end;

procedure findArticulation;
var
	i, v, alt : LongInt;
	p : PList;
	alternative : IntArray;
begin
	for i := 1 to n do begin
		articulation[i] := false;
		alternative[i] := i;
	end;
	for i := n downto 1 do begin
		v := order[i];
		p := sons[v];
		while p <> nil do begin
			if alternative[p^.item] = v then
				articulation[v] := true;
			p := p^.next;
		end;
		alt := v;
		p := incoming[v];
		while p <> nil do begin
			if preorder[alternative[p^.item]] < preorder[alt] then
				alt := alternative[p^.item];
			p := p^.next;
		end;
		propagateAlternativeDown(v, alt, alternative);
	end;
end;

procedure writeOutput;
var
	i, counter : LongInt;
	winners : IntArray;
begin
	counter := 0;
	for i := 1 to n do
		if articulation[i] then begin
			inc(counter);
			winners[counter] := i;
		end;
	writeln(counter);
	for i := 1 to counter do begin
		if i <> 1 then write(' ');
		write(winners[i]);
	end;
	writeln;
end;

begin
	readInput;
	createTree;
	findArticulation;
	writeOutput;
end.
