#include <bits/stdc++.h>

using namespace std;

using i64 = int64_t;

const i64 MOD = 1e9 + 7;


struct LowLink{
    vector<vector<int>>& edges;
    // 関節点
    vector<int> art;
    vector<pair<int,int>> bridge;

    vector<int> used, ord, low;
    int k;

    void dfs(int idx, int par){
        ord[idx] = k++;
        low[idx] = ord[idx];
        bool is_art = false;
        int cnt = 0;
        for(auto& to : edges[idx]){
            if(ord[to] == -1){
                ++cnt;
                dfs(to, idx);
                low[idx] = min(low[idx], low[to]);
                is_art |= par != -1 && low[to] >= ord[idx];
                if(ord[idx] < low[to])
                    bridge.emplace_back(idx, to);
            }else if(to != par)
                low[idx] = min(low[idx], ord[to]);
        }
        is_art |= (par == -1 && cnt > 1);
        if(is_art)
            art.emplace_back(idx);
    }

    LowLink(vector<vector<int>>& edges) :
        edges(edges),
        ord(edges.size(), -1),
        low(edges.size(), 0),
        k(0)
    {
        for(int i = 0; i < edges.size(); ++i)
            if(ord[i] == -1)
                dfs(i, -1);
        for(auto& b : bridge)
            b = make_pair(min(b.first, b.second), max(b.first, b.second));
        sort(art.begin(), art.end());
        sort(bridge.begin(), bridge.end());
    }
};


signed main(){
    int n, m;
    cin >> n >> m;
    vector<pair<int,int>> v(m);
    vector<vector<int>> edges(n);
    for(int i = 0; i < m; ++i){
        vector<int> l(2);
        for(auto& x : l)
            cin >> x;
        sort(l.begin(), l.end());
        v[i] = make_pair(l.front(), l.back());
        edges[l[0]].emplace_back(l[1]);
        edges[l[1]].emplace_back(l[0]);
    }
    LowLink ll(edges);
    for(auto& x : ll.art)
        cout << x << endl;
}


#include <vector>
#include <iostream>
#include <algorithm>
#include <set>

using namespace std;
#define MAX 10000

vector<int> G[MAX];
int n;
bool visited[MAX];
int treeIdx[MAX], parent[MAX], lowest[MAX], treeNodeCounter;

void dfs(int curIdx, int prev)
{
	treeIdx[curIdx] = lowest[curIdx] = treeNodeCounter;
	treeNodeCounter++;

	visited[curIdx] = true;
	int next;

	for (int i = 0; i < G[curIdx].size(); ++i)
	{
		next = G[curIdx][i];
		if (!visited[next])
		{
			parent[next] = curIdx;
			dfs(next, curIdx);
			lowest[curIdx] = min(lowest[curIdx], lowest[next]);
		}
		else if (next != prev)
		{
			lowest[curIdx] = min(lowest[curIdx], treeIdx[next]);
		}
	}
}

void criticalPoints()
{
	for (int i = 0; i < n; ++i)
		visited[i] = false;
	treeNodeCounter = 1;

	dfs(0, -1);

	set<int> s;
	int np = 0;
	for (int i = 1; i < n; ++i)
	{
		int p = parent[i];
		if (0 == p) np++;
		else if (treeIdx[p] <= lowest[i])
			s.insert(p);
	}
	if (np > 1) cout << 0 << endl;
	for (auto v : s) cout << v << endl;
}

int main()
{
	int m;
	cin >> n >> m;

	for (int i = 0; i < m; ++i)
	{
		int s, t;
		cin >> s >> t;
		G[s].push_back(t);
		G[t].push_back(s);
	}
	criticalPoints();

	return 0;
}