//tarjan求割点
int cut[20005];
int dfn[20005] ,low[20005], times;
void tarjan(int u, int root)
{
dfn[u] = low[u] = ++ times;
int flag = 0;
for(int i = head[u] ; i != -1 ; i = edge[i].next)
{
int v = edge[i].t;
if(!dfn[v])
{
tarjan(v, root);
low[u] = min(low[u], low[v]);
if(low[v] >= dfn[u])
{
flag ++;
if (u != root || flag > 1)
cut[u] = 1;
}
}
else
low[u] = min(low[u],dfn[v]);
}
}
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define DBG printf("this is a input\n")
#define fi first
#define se second
#define mk(a, b) make_pair(a,b)
#define p_queue priority_queue
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
int n , m, cnt = 0;
int head[100005];
struct node
{
int f, t, next;
}edge[200005];
int low[100005] ,dfn[100005] , times = 1;
int cut[100005];
void add(int f, int t)
{
edge[cnt].f = f;
edge[cnt].t = t;
edge[cnt].next = head[f];
head[f] = cnt ++;
}
void tarjan(int u, int root)
{
int tot = 0; //用于计算根节点的子树个数
low[u] = dfn[u] = ++times; //时间戳
for(int i = head[u] ; i != -1 ; i = edge[i].next)
{
int v = edge[i].t;
if(!dfn[v]) //如果没被访问
{
tarjan(v,root);
low[u] = min(low[u],low[v]); //更新时间戳
if(low[v] >= dfn[u] && u != root) //如果更新后只能到达父节点,并且该点不是根节点,则为割点
cut[u] = 1;
}
else
low[u] = min(low[u],dfn[v]);
}
if(u == root && tot >= 2) //如果根节点子树大于1,则根节点也为割点
cut[root] = 1;
}
int main(void)
{
ios::sync_with_stdio(0);
cin.tie(0);
cin>>n>>m;
mem(head,-1);
for(int i = 1 ; i <= m ; i ++)
{
int u ,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
for(int i = 1 ; i <= n ; i ++)
if(!dfn[i])
tarjan(i,i);
int ans = 0;
for(int i = 1 ; i <= n ; i ++)
if(cut[i])
ans ++;
cout<<ans<<endl;
for(int i = 1 ;i <= n ; i ++)
if(cut[i])
cout<<i<<" ";
}