#include<iostream>
#include<list>
#include<queue>
#include<set>
#include<algorithm>
#include<stdio.h>
using namespace std;
int n, m;
struct Node {
	//int id;
	list<int> next;
};
Node graph[100005];
int prenum[100005];
int parent[100005];
int lowest[100005];
set<int> answer;
int rootCount;
void dfs(int curNodeId,int step) {
	int low = prenum[curNodeId];
	list<int>::iterator it = graph[curNodeId].next.begin();
	list<int>::iterator end = graph[curNodeId].next.end();
	for (it; it != end; it++) {
		int id = *it;
		if (prenum[id] == 0) {
			parent[id] = curNodeId;
			prenum[id] = step + 1;
			dfs(id, step + 1);
			low = min(low, lowest[id]);
			if (step == 1) {
				rootCount++;
			}
		}
		else {
			low = min(low, prenum[id]);
		}
	}
	lowest[curNodeId] = low;
}
void findArticulationPoint() {
	if (rootCount >= 2) {
		answer.insert(0);
	}
	int p;
	for (int i = 1; i < n; i++) {
		p = parent[i];
		if (p == 0) {
			continue;
		}
		if (prenum[p] <= lowest[i]) {
			answer.insert(p);
		}
	}
	vector<int> ans;
	for (set<int>::iterator it = answer.begin(); it != answer.end(); it++) {
		ans.push_back(*it);
	}

	sort(ans.begin(), ans.end());

	for (vector<int>::iterator it = ans.begin(); it != ans.end(); it++) {
		printf("%d\n", *it);
	}
}
int main() {
	scanf("%d %d", &n,&m);
	int a, b;
	for (int i = 0; i < m; i++) {
		scanf("%d %d", &a,&b);
		graph[a].next.push_back(b);
		graph[b].next.push_back(a);
	}

	prenum[0] = 1;
	dfs(0,1);

	findArticulationPoint();

	/*for (int i = 0; i < n; i++) {
		cout << i << " " << prenum[i] << " " << parent[i] << " " << lowest[i] << endl;
	}*/
}


#include <algorithm>
#include <bitset>
#include <cctype>
#include <complex>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

using namespace std;

inline int toInt(string s) {int v; istringstream sin(s);sin>>v;return v;}
template<class T> inline string toString(T x) {ostringstream sout;sout<<x;return sout.str();}
template<class T> inline T sqr(T x) {return x*x;}

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;

#define all(a)  (a).begin(),(a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define pb push_back
#define mp make_pair
#define each(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define exist(s,e) ((s).find(e)!=(s).end())
#define range(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n)  range(i,0,n)
#define clr(a,b) memset((a), (b) ,sizeof(a))
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;

const double eps = 1e-10;
const double pi  = acos(-1.0);
const ll INF =1LL << 62;
const int inf =1 << 29;

struct node {int to,cost; };

typedef vector< vector<node> > G;

inline void add_edge(G& g,int from,int to,int cost=1){
	node in; in.to=to; in.cost=cost;
	g[from].pb(in);
}

inline void add_both_edge(G& g,int from,int to,int cost=1){	
	add_edge(g,from,to,cost);
	add_edge(g,to,from,cost);
}

void dfs(const G& g,int cur,int prev,int &k,vi& order, vi& low,vi& parent) {
	order[cur]=k++;
	low[cur]=order[cur];

	rep(i,g[cur].size()){
		int to=g[cur][i].to;
		if(order[to]==-1){
			parent[to]=cur;
			dfs(g,to,cur,k,order,low,parent);
			low[cur]=min(low[cur],low[to]);
		}else if(to!=prev)
			low[cur]=min(low[cur],order[to]);
	}
	return;
}

void Lowlink(const G& g, vi& order,vi& low,vi& parent) {
	int v=g.size();
	order.assign(v,-1);
	low.resize(v);
	parent.resize(v);
	int k=0;
	parent[0]=-1;
	dfs(g,0,-1,k,order,low,parent);
	return ;
}

int main(void){
	int n,m;
	cin >> n >> m;
	G graph(n);
	rep(i,m){
		int a,b;
		cin >> a >> b;
		add_both_edge(graph,a,b);
	}
	vi order,low,parent;
	Lowlink(graph,order,low,parent);

	rep(i,n){
		if(i){
			bool ok=false;
			rep(j,graph[i].size()){
				int to=graph[i][j].to;
				if(i==parent[to]&&order[i]<=low[to])
					ok=true;
			}
			if(ok) cout << i << endl;
		}else{
			int d=0;
			rep(j,n) if(parent[j]==0) d++;
			if(d>=2) cout << i << endl;
		}
	}
	return 0;
}