#include <iostream>
#include <vector>
#include <set>
using namespace std;

static const int NIL = -1;

struct Vertex {
    vector<int> link;
    int parent = NIL;
    int ord;
    int lowlink;
    bool is_visit = false;
};

class ArticulationPoint {
private:
    int n;
    vector<Vertex> graph;
    int timer = 1;

public:
    ArticulationPoint() {}

    ArticulationPoint(int n)
    {
        this->n = n;
        graph.resize(n);
        int edge;
        cin >> edge;
        int s, t;
        for (int e = 0; e < edge; e++)
        {
            cin >> s >> t;
            graph[s].link.push_back(t);
            graph[t].link.push_back(s);
        }
    }

    void dfs(int current)
    {
        graph[current].is_visit = true;
        graph[current].ord = graph[current].lowlink = timer;
        timer++;

        for(int next : graph[current].link)
        {
            if(!graph[next].is_visit)
            {
                graph[next].parent = current;
                dfs(next);
                graph[current].lowlink = min(graph[current].lowlink, graph[next].lowlink); // 3.
            }
            else if(next != graph[current].parent)
            {
                // １回の移動で行くことのできる訪問済みの頂点は，Backedgeを除けば自分の親しかいない
                // つまりこのブロックにくるのはnextがBackedgeを通った訪問済みの頂点のとき
                graph[current].lowlink = min(graph[current].lowlink, graph[next].ord);
            }

        }
    }

    void articulation_point()
    {
        set<int> art_point;
        int root = 0;

        dfs(root);

        int root_child_num = 0;
        for(int u = 0; u < n; u++)
        {
            int p = graph[u].parent;
            if(p == NIL) continue;
            if(p == root)
            {
                root_child_num++;
                if(root_child_num >= 2)
                    art_point.insert(root);
            }
            else if(graph[p].ord <= graph[u].lowlink)
            {
                art_point.insert(p);
            }
        }

        for(int x : art_point)
            cout << x << endl;
    }
};

int main()
{
    int n;
    cin >> n;
    ArticulationPoint articulationPoint(n);
    articulationPoint.articulation_point();
}

#include <bits/stdc++.h>
using namespace std;

// Template Headers {{{
using pii = pair<int, int>; using vpii = vector<pii>;
using vi = vector<int>; using vvi = vector<vi>;
using ll = long long; using vll = vector<long long>;
template <class T> using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T> istream &operator>>(istream &, vector<T> &);
template <class T> ostream &operator<<(ostream &, const vector<T> &);
template <class T, class U> istream &operator>>(istream &, pair<T, U> &);
template <class T, class U> ostream &operator<<(ostream &, const pair<T, U> &);
template <class T> struct Inf { static constexpr T inf() { return std::numeric_limits<T>::has_infinity() ? std::numeric_limits<T>::infinty() : std::numeric_limits<T>::max(); } };
template <> struct Inf<int> { static constexpr int inf() { return 0x3f3f3f3f; } };
template <> struct Inf<long long> { static constexpr long long inf() { return 0x3f3f3f3f3f3f3f3fLL; } };
constexpr int INF = Inf<int>::inf(); constexpr ll BINF = Inf<ll>::inf();
// mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
// }}}

int solve() {
	int n, m; cin >> n >> m;
	vvi g(n);
	for (int i = 0; i < m; i++) {
		int u, v; cin >> u >> v;
		g[u].push_back(v); g[v].push_back(u);
	}
	int timer = 0;
	vi stTime(n, INF), enTime(n, INF);
	vi low(n);
	vi ans(n);
	function<void(int, int)> dfs = [&] (int u, int p) {
		stTime[u] = timer++;
		low[u] = stTime[u];
		int jai = 0;
		for (int v : g[u]) {
			if (v == p) continue;
			if (stTime[v] >= INF) {
				// tree edge
				dfs(v, u);
				low[u] = min(low[u], low[v]);
				if (low[v] >= stTime[u] && p != -1) ans[u] = 1;
				jai++;
			} else if (enTime[v] >= INF) {
				// back edge
				low[u] = min(low[u], stTime[v]);
			}
		}
		enTime[u] = timer;
		if (p == -1 && jai > 1) ans[u] = 1;
	};
	dfs(0, -1);
	for (int i = 0; i < n; i++) if (ans[i]) cout << i << endl;
	return 0;
}

// Template Main {{{
int main() {
	ios::sync_with_stdio(0);
	// precompute();
	// int t; cin >> t; for (int i=1;i<=t;i++)
	solve();
	// cout << "Case #" << i << ": ", solve();
	return 0;
}

template <class T> istream &operator>>(istream &is, vector<T> &v) {
	for (auto it=v.begin();it!=v.end();++it) is >> *it;
	return is;
}

template <class T> ostream &operator<<(ostream &os, const vector<T> &v) {
	for (auto it=v.begin();it!=v.end();) os << *it, os << " \n"[++it==v.end()];
	return os;
}

template <class T, class U> istream &operator>>(istream &is, pair<T, U> &p) {
	return is >> p.first >> p.second;
}

template <class T, class U> ostream &operator<<(ostream &os, const pair<T, U> &p) {
	return os << p.first << ' ' << p.second;
}
// }}}

// vim: fdm=marker

