新学的知识,实现起来有点不熟练
要注意的就是对于 dfs 树根的特判
并且注意“存在即合理”的特性
//这里写代码片
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=100005;
struct node{
int x,y,nxt;
};
node way[N<<1];
int st[N],tot=0,n,m,clo=0;
int pre[N],low[N],ans=0;
bool p[N];
void add(int u,int w)
{
tot++;
way[tot].x=u;way[tot].y=w;way[tot].nxt=st[u];st[u]=tot;
tot++;
way[tot].x=w;way[tot].y=u;way[tot].nxt=st[w];st[w]=tot;
}
void dfs(int u,int fa)
{
int lowu=pre[u]=++clo;
int ch=0;
for (int i=st[u];i;i=way[i].nxt)
{
int v=way[i].y;
if (!pre[v])
{
ch++;
dfs(v,u);
lowu=min(lowu,low[v]);
if (low[v]>=pre[u]) //存在即合理
{
if (!p[u]) ans++;
p[u]=1;
}
// if (low[v]>pre[u]) i是桥
}
else if (pre[v]&&v!=fa)
{
lowu=min(lowu,pre[v]);
}
}
if (fa==-1&&ch==1) {
if (p[u]) ans--;
p[u]=0; //根节点 fa=-1
}
low[u]=lowu;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int u,w;
scanf("%d%d",&u,&w);
add(u,w);
}
memset(pre,0,sizeof(pre));
memset(p,0,sizeof(p));
for (int i=1;i<=n;i++)
if (!pre[i]) dfs(i,-1);
printf("%d\n",ans);
for (int i=1;i<=n;i++)
if (p[i]) printf("%d ",i);
return 0;
}