题目描述
给出一个nnn个点,mmm条边的无向图,求图的割点。
输入输出格式
输入格式:
第一行输入n,m
下面m行每行输入x,y表示x到y有一条边
输出格式:
第一行输出割点个数
第二行按照节点编号从小到大输出节点,用空格隔开
输入输出样例
输入样例#1:
6 7
1 2
1 3
1 4
2 5
3 5
4 5
5 6
输出样例#1:
1
5
说明
对于全部数据,n≤20000
点的编号均大于0小于等于n。
tarjan图不一定联通。
题解:
Tarjain求割点
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=200010;
int n,m,idx,t,tot;
int head[N],dfn[N],low[N];
int nxt[N],adj[N];
bool cut[N];
void add(int u,int v)
{
t++;
nxt[t]=head[u];
head[u]=tot;
adj[t]=v;
}
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++idx;
int child=0;
for(i=head[u];i!=0;i=pre[i].mark)
{
int nx=pre[i].nxt;
if(!dfn[nx])
{
tarjan(nx,fa);
low[u]=min(low[u],low[nx]);
if (LOW[nx]>=dfn[u]&&u!=fa)
cut[u]=1;
if(u==fa)
child++;
}
low[u]=min(low[u],DFN[nx]);
}
if (child>=2&&u==fa)
cut[u]=1;
}
int main()
{
scanf ("%d%d",&n,&m);
int x,y,i;
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
add(a,b);
add(b,a);
}
for(i=1;i<=n;i++)
if(dfn[i]==0)
tarjan(i,i);
for(i=1;i<=n;i++)
if(cut[i])
tot++;
printf("%d\n",tot);
for(i=1;i<=n;i++)
if(cut[i])
printf("%d ",i);
return 0;
}