#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 10,inf = 0x3f3f3f3f;
vector<int> g[N]; // 邻接表存储图
int dfn[N],low[N],id; // dfn:时间戳,low:能回溯到的最小dfn,f:父节点,id:时间戳计数器
int vis[N]; // 标记节点是否为割点
int ans; // 割点数量
int n,m; // 顶点数,边数
void tarjan(int x,int fa) // Tarjan算法,x:当前节点,fa:父节点
{
dfn[x] = low[x] = ++id; // 初始化当前节点的dfn和low值
int cnt = 0; // 记录当前节点的子节点数量(用于判断根节点是否为割点)
for(int i = 0; i < g[x].size(); i++)
{
int y = g[x][i]; // 邻接节点y
if(dfn[y] == 0){ // 如果y未被访问过(树边)
cnt++; // 子节点计数+1
tarjan(y,x); // 递归遍历子节点
low[x] = min(low[x],low[y]); // 更新当前节点的low值
// 判断割点条件:
if(fa == 0){ // 如果x是根节点
if(cnt >= 2) vis[x] = 1; // 根节点有>=2个子树则是割点
}
else if(low[y] >= dfn[x]) vis[x] = 1; // 非根节点:存在子节点y满足low[y]>=dfn[x]
}
else low[x] = min(low[x],dfn[y]); // 回边,更新low值
}
}
int main()
{
cin >> n >> m;
// 读入图数据,构建无向图
for(int i = 1; i <= m; i++)
{
int x,y; cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
// 遍历所有连通分量(因为图可能不连通)
for(int i = 1; i <= n; i++)
{
if(dfn[i] == 0) // 如果节点i未被访问过
tarjan(i,0); // 从i开始Tarjan算法,父节点设为0(表示根节点)
}
// 统计割点数量
for(int i = 1; i <= n; i++)
if(vis[i]) ans++;
// 输出结果
cout << ans << endl;
for(int i = 1; i <= n; i++)
if(vis[i])
cout << i << " ";
return 0;
}