

#include<bits/stdc++.h>
using namespace std;
#define inf INT_MAX
#define INF LLONG_MAX
#define ll long long
#define ull unsigned long long
#define M (int)(1e9+7)
#define P pair<int,int>
#define FOR(i,m,n) for(int i=(int)m;i<(int)n;i++)
#define RFOR(i,m,n) for(int i=(int)m;i>=(int)n;i--)
#define rep(i,n) FOR(i,0,n)
#define rrep(i,n) RFOR(i,n,0)
#define all(a) a.begin(),a.end()
const int vx[4] = {0,1,0,-1};
const int vy[4] = {1,0,-1,0};
#define F first
#define S second
#define PB push_back
#define EB emplace_back
#define int ll
#define vi vector<int>
#define IP pair<int,P>
#define PI pair<P,int>
#define PP pair<P,P>
#define Yes(f){cout<<(f?"Yes":"No")<<endl;}
#define YES(f){cout<<(f?"YES":"NO")<<endl;}
int Madd(int x,int y) {return (x+y)%M;}
int Msub(int x,int y) {return (x-y+M)%M;}
int Mmul(int x,int y) {return (x*y)%M;}



template< typename T >
struct edge {
  int src, to;
  T cost;

  edge(int to, T cost) : src(-1), to(to), cost(cost) {}

  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WG = vector< Edges< T > >;
using UG = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;

template< typename T >
struct LowLink {
  const WG<T> &g;
  vector< int > used, ord, low;
  vector< int > articulation;
  vector< pair< int, int > > bridge;

  LowLink(const WG<T> &g) : g(g) {}

  int dfs(int idx, int k, int par) {
    used[idx] = true;
    ord[idx] = k++;
    low[idx] = ord[idx];
    bool is_articulation = false;
    int cnt = 0;
    for(auto &e : g[idx]) {
      if(!used[e.to]) {
        ++cnt;
        k = dfs(e.to, k, idx);
        low[idx] = min(low[idx], low[e.to]);
        is_articulation |= ~par && low[e.to] >= ord[idx];
        if(ord[idx] < low[e.to]) bridge.emplace_back(minmax(idx, (int) e.to));
      } else if(e.to != par) {
        low[idx] = min(low[idx], ord[e.to]);
      }
    }
    is_articulation |= par == -1 && cnt > 1;
    if(is_articulation) articulation.push_back(idx);
    return k;
  }

  virtual void build() {
    used.assign(g.size(), 0);
    ord.assign(g.size(), 0);
    low.assign(g.size(), 0);
    int k = 0;
    for(int i = 0; i < g.size(); i++) {
      if(!used[i]) k = dfs(i, k, -1);
    }
  }
};

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout<<fixed<<setprecision(20);

  int n,m;
  cin>>n>>m;
  WG<int> es(n);
  rep(i,m){
    int x,y;
    cin>>x>>y;
    es[x].PB(edge<int>(y,1));
    es[y].PB(edge<int>(x,1));
  }

  LowLink<int> lowlink(es);
  lowlink.build();
  sort(all(lowlink.articulation));
  for(int x:lowlink.articulation){
    cout<<x<<endl;
  }


}

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

int timer = 0;

struct needed {

	needed(int verNum) {
		for (int i = 0; i < verNum; i++) {
			visited.push_back(false);
			preNum.push_back(1 << 30);
			lowest.push_back(1 << 30);
			parent.push_back(-1);
		}
	}

	vector<bool> visited;
	vector<int> preNum; //?¨?????????????
	vector<int> lowest;
	vector<int> parent;

};

void DFS(int current, int previous, vector<int> verVal[], needed &need) {

	need.preNum[current] = timer;
	need.lowest[current] = timer;
	timer++;

	need.visited[current] = true;

	for (int i = 0; i < verVal[current].size(); i++) {
		int next = verVal[current][i];
		if (!need.visited[next]) {
			need.parent[next] = current;
			DFS(next, current, verVal, need);
			need.lowest[current] = min(need.lowest[current], need.lowest[next]);
		}
		else if (next != previous) {
			need.lowest[current] = min(need.lowest[current], need.preNum[next]);
		}
	}
}

void ArticulationPoint(vector<int> verVal[], int verNum) {

	needed need(verNum);
	DFS(0, -1, verVal, need);

	set<int> artPoints;
	int childNumOfRoot = 0;
	//root??????????????¨??¨
	for (int i = 1; i < verNum; i++) {
		int nowP = need.parent[i];
		if (nowP == 0) childNumOfRoot++;
		else if (need.preNum[nowP] <= need.lowest[i])
			artPoints.insert(nowP);
	}
	//root?????¢?????????????????????????????????????????£??????????????§?????????
	if (childNumOfRoot > 1) artPoints.insert(0);

	for (set<int>::iterator it = artPoints.begin(); it != artPoints.end(); it++)
		cout << *it << endl;
}

int main() {

	int verNum, edgeNum;
	cin >> verNum >> edgeNum;
	vector<int> verVal[100000];

	for (int i = 0; i < edgeNum; i++) {
		int firVal, secVal;
		cin >> firVal >> secVal;
		verVal[firVal].push_back(secVal);
		verVal[secVal].push_back(firVal);
	}

	ArticulationPoint(verVal, verNum);

	return 0;
}