/*************************************************************************
 *                                                                       *
 *                       Pogromcy Algorytmów 2004                        *
 *                                                                       *
 *   Rozwiązanie zadania: Bajtocka Agencja Informacyjna                  *
 *   Plik:                bai.cpp                                        *
 *   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)
 */

#include <cstdio>
#include <vector>

using namespace std;

// pomocnicze makra
#define REP(i,n) for(int i = 0; i < (n); ++i)
#define FORD(i,b,a) for(int i = (b); i >= (a); --i)

// dzięki temu unikniemy ostrzeżenia podczas kompilacji,
// że porównujemy liczby ze znakiem z liczbami bez znaku
template <class T> inline int size(T v) {return v.size();}

typedef vector<int> vi;
typedef vector<vi> vvi;

// dane wejsciowe
int n;
vvi incoming, outgoing;

// opis drzewa DFS
vi preorder;
vi order;
vvi sons;

// wyniki
vector<bool> articulation;

void read() {
	int m;
	scanf("%d%d", &n, &m);
	incoming.assign(n, vi());
	outgoing.assign(n, vi());
	REP(i,m) {
		int a, b;
		scanf("%d%d", &a, &b);
		--a;
		--b;
		outgoing[a].push_back(b);
		incoming[b].push_back(a);
	}
}

void dfs(int v, int f, int &counter, vector<bool> &visited) {
	if (visited[v]) return;
	visited[v] = true;
	preorder[v] = counter++;
	order.push_back(v);
	if (f != -1) sons[f].push_back(v);
	REP(i,size(outgoing[v]))
		dfs(outgoing[v][i], v, counter, visited);
}

void dfsTree() {
	preorder.assign(n, 0);
	sons.assign(n, vi());
	order.clear();
	vector<bool> visited(n, false);
	int counter = 0;
	dfs(0, -1, counter, visited);
}

void propagateDownAlternative(int v, vi &alternative, int alt) {
	if (preorder[alternative[v]] <= preorder[alt]) return;
	alternative[v] = alt;
	REP(i,size(sons[v]))
		propagateDownAlternative(sons[v][i], alternative, alt);
}

void findArticulation() {
	articulation.assign(n, false);
	vi alternative(n, 0);
	REP(i,n) alternative[i] = i;
	FORD(i,n-1,0) {
		int v = order[i];
		REP(j,size(sons[v]))
			articulation[v] =
				articulation[v]
				|| alternative[sons[v][j]] == v;
		int alt = v;
		REP(j,size(incoming[v])) {
			int otherAlt = alternative[incoming[v][j]];
			if (preorder[alt] > preorder[otherAlt])
				alt = otherAlt;
		}
		propagateDownAlternative(v, alternative, alt);
	}
}

void output() {
	vi list;
	REP(i,n)
		if (articulation[i])
			list.push_back(i);
	printf("%d\n", size(list));
	REP(i,size(list)) {
		if (i != 0) printf(" ");
		printf("%d", list[i] + 1);
	}
	printf("\n");
}

int main() {
	read();
	dfsTree();
	findArticulation();
	output();
}
