#include <cstdio>
#include <algorithm>
#include <vector>
#include <set>

using namespace std;

using Weight=long long;
static const Weight INF=1LL<<57;

struct Edge {
    size_t src, dst;
    Weight weight;
    Edge() {}
    Edge(size_t src, size_t dst, Weight weight=1):
        src(src), dst(dst), weight(weight)
    {}
};

bool operator<(const Edge &e, const Edge &f) {
    if (e.weight != f.weight) {
        return e.weight > f.weight;
    } else {
        return e.src!=f.src? e.src<f.src : e.dst<f.dst;
    }
}

using Edges=vector<Edge>;
using Vertex=vector<Edge>;
using Graph=vector<Vertex>;

void join(Graph &g, size_t s, size_t d, Weight w=1) {
    // non-directed
    g[s].push_back(Edge(s, d, w));
    g[d].push_back(Edge(d, s, w));
}

void connect(Graph &g, size_t s, size_t d, Weight w=1) {
    // directed
    g[s].push_back(Edge(s, d, w));
}

void visit(
    const Graph &g, size_t v, size_t u, set<size_t> &artpoint,
    vector<size_t> &num, vector<size_t> &low, int &time
) {
    low[v] = num[v] = ++time;
    for (const Edge &e: g[v]) {
        size_t w=e.dst;
        if (!num[w]) {
            visit(g, w, v, artpoint, num, low, time);
            low[v] = min(low[v], low[w]);

            if (num[v]==1? num[w]!=2 : low[w]>=num[v])
                artpoint.insert(v);

        } else {
            low[v] = min(low[v], num[w]);
        }
    }
}

set<size_t> get_artpoint(const Graph &g) {
    const size_t V=g.size();

    vector<size_t> low(V), num(V);
    set<size_t> artpoint;
    for (size_t u=0; u<V; ++u) if (!num[u]) {
        int time=0;
        visit(g, u, -1, artpoint, num, low, time);
    }

    return artpoint;
}

int main() {
    size_t V, E;
    scanf("%zu %zu", &V, &E);

    Graph g(V);
    for (size_t i=0; i<E; ++i) {
        size_t s, t;
        scanf("%zu %zu", &s, &t);

        join(g, s, t);
    }

    set<size_t> artpoint=get_artpoint(g);

    for (size_t v: artpoint)
        printf("%zu\n", v);

    return 0;
}
// Enjoy your stay.

#include <bits/stdc++.h>

#define EPS 1e-9
#define INF 1070000000LL
#define MOD 1000000007LL
#define fir first
#define foreach(it,X) for(auto it=(X).begin();it!=(X).end();it++)
#define ite iterator
#define mp make_pair
#define mt make_tuple
#define rep(i,n) rep2(i,0,n)
#define rep2(i,m,n) for(int i=m;i<(n);i++)
#define pb push_back
#define sec second
#define sz(x) ((int)(x).size())

using namespace std;

typedef istringstream iss;
typedef long long ll;
typedef pair<ll,ll> pi;
typedef stringstream sst;
typedef vector<ll> vi;

const int MAXN = 100010;

int n;
vector<int> g[100010];

int zeit, dis[MAXN], fin[MAXN], low[MAXN], par[MAXN], dep[MAXN];
int kodat[MAXN], koptr[MAXN + 1];
void dfsInfo(int u,int oy,int d){
	dis[u] = low[u] = zeit++; par[u] = oy; dep[u] = d;
	int v;
	rep(i,sz(g[u])) if((v = g[u][i]) != oy){
		if(!~dis[v]){
			dfsInfo(v, u, d + 1);
			low[u] = min(low[u], low[v]);
		} else {
			low[u] = min(low[u], dis[v]);
		}
	}
	fin[u] = zeit++;
}

void dfsInfos(){
	memset(dis, ~0, n*4); zeit = 0;
	rep(u,n) if(!~dis[u]) dfsInfo(u, -1, 0);
	rep(u,n){
		int &j = koptr[u + 1] = koptr[u];
		rep(i,sz(g[u])) if(u == par[g[u][i]]) kodat[j++] = g[u][i];
	}
}

bool produce(int u,int v){
	return (dis[u] <= dis[v] && fin[u] >= fin[v]);
}

int related(int u,int v){
	int s = koptr[u], e = koptr[u+1], h;
	while(s+1 < e){
		h = (s + e) >> 1;
		(dis[kodat[h]] <= dis[v]) ? s = h : e = h;
	}
	return kodat[s];
}

bool isBridge(int u,int v){
	if(dis[u] > dis[v]) swap(u, v);
	return (u == par[v] && dis[v] <= low[v]);
}

int Count[MAXN];

int main(){
	cin.tie(0);
	ios_base::sync_with_stdio(0);

	int m;
	cin>>n>>m;
	rep(i,m){
		int a,b;
		cin>>a>>b;
		g[a].pb(b);
		g[b].pb(a);
	}
	rep(i,n)sort(g[i].begin(),g[i].end());
	dfsInfos();
	Count[0] = -1;
	rep(i,n)rep2(j,koptr[i],koptr[i+1]){
		Count[i] += dis[i] <= low[kodat[j]];
	}
	rep(i,n){
		if(Count[i] > 0)cout<<i<<endl;
	}
	//rep(i,n)cout<<Count[i]<<" ";cout<<endl;
}