给定一张 n n n个点, m m m条边的无向连通图,问有多少个点满足删除这个点后,剩下的图无环且联通
数据范围: n ≤ 1 0 5 , m ≤ 1 0 5 n\leq 10^5,m\leq 10^5 n≤105,m≤105
这个点不能是割点
割完之后的图必定是一棵树(边数+1=点数)
记录度数(连接的边的个数),用 t a r j a n tarjan tarjan求割点即可
时间复杂度: O ( n + m ) O(n+m) O(n+m)
#include
#include
#include
#include
#include
#define LL long long
#define N 100010
using namespace std;int n,m,x,y,rd[N],l[N],tot,ans,dfn[N],low[N],cnt,rt;
bool ds1[N],flg,hs[N],cut[N];
struct node{int next,to;}e[N*2];
inline void add(int u,int v){e[++tot]=(node){l[u],v};l[u]=tot;return;}
inline LL read()
{
char c;LL d=1,f=0;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
inline void tarjan(int x)
{
dfn[x]=low[x]=++cnt;
int flag=0;
for(register int i=l[x];i;i=e[i].next)
{
int y=e[i].to;
if(dfn[y]==0)
{
tarjan(y);
low[x]=min(low[x],low[y]);
if(low[y]>=dfn[x])
{
flag++;
if(flag>1||x!=rt) cut[x]=true;
}
}else low[x]=min(low[x],dfn[y]);
}
return;
}
signed main()
{
n=read();m=read();
for(register int i=1;i<=m;i++)
{
x=read();y=read();
rd[x]++;rd[y]++;
add(x,y);add(y,x);
}
for(register int i=1;i<=n;i++) if(dfn[i]==0) tarjan(rt=i);
for(register int i=1;i<=n;i++) if(cut[i]==0&&n-1==m-rd[i]+1) ans++;
printf("%d\n",ans);
for(register int i=1;i<=n;i++) if(cut[i]==0&&n-1==m-rd[i]+1) printf("%d ",i);
}