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

using namespace std;

vector<int> articulation_points;
vector<int> graph[100000];
int ord[100000],low[100000];
bool visited[100000];

int visit_time = 0;

void dfs(int v,int p){
  visited[v] = true;
  ord[v] = visit_time;
  low[v] = ord[v];
  visit_time++;
  bool is_articulation = false;
  int cnt = 0;
  for(int i=0;i<graph[v].size();++i){
    if(!visited[graph[v][i]]){
      cnt++;
      dfs(graph[v][i],v);
      low[v] = min(low[v],low[graph[v][i]]);
      if(p!=-1&&ord[v]<=low[graph[v][i]]) is_articulation = true;
    }else if(graph[v][i]!=p){
      low[v] = min(low[v],ord[graph[v][i]]);
    }
  }

  if(p==-1&&cnt > 1) is_articulation = true;
  if(is_articulation) articulation_points.emplace_back(v);
}

int main(){
  int N , M ;
  cin >> N >> M;
  for(int i=0;i<M;++i){
    int s,t;
    cin >> s >> t;
    graph[s].push_back(t);   
    graph[t].push_back(s);
  }
  
  for(int i=0;i<N;++i){
    if(!visited[i]) dfs(i,-1);
  }
  
  sort(articulation_points.begin(),articulation_points.end());
  for(const auto &a:articulation_points){
    cout << a << endl;
  }
  return 0;
}
#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();
}
