🎭 🎭 🎭
看这个搞懂的
:DFS树由树边即若干条返祖边构成
int n,m;
set<int>ans;
vector<int>vc[22222];
int tot,dfn[22222],low[22222];//时间戳以及连通分量中的最小时间戳
void tarjan(int x,int fx,int root)//当前结点,根节点,父结点
{
dfn[x]=low[x]=++tot;
int child=0;
for(auto v:vc[x])
{
if(v==fx) continue;
++child;
if(dfn[v]==0)
{
tarjan(v,x,root);
low[x]=min(low[x],low[v]);
if(x!=root&&low[v]>=dfn[x])//x不是根节点且v不通过x到达不了祖先
ans.insert(x);
if(x==root&&child>=2) //特判根节点//x是根节点且有两个以上的孩子
ans.insert(x);
}
else low[x]=min(low[x],dfn[v]);//此时x--->v即为一条返祖边
}
}
signed main()
{
tot=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
cin>>n>>m;
rpp(i,m)
{
int x,y;cin>>x>>y;
vc[x].push_back(y),vc[y].push_back(x);
}
rpp(i,n) if(dfn[i]==0) tarjan(i,i,i);
cout<<ans.size()<<endl;
for(auto it=ans.begin();it!=ans.end();++it) cout<<*it<<" ";
cout<<endl;
stop;
return 0;
}