第一次接触求割点,虽然是模板题,但是还是出了些问题,好在AC了,用的是并查集判断是否在同一个连通分量中。
/*************************************************************************
> File Name: main.cpp
> Author:Eagles
> Mail:None
> Created Time: 2018年09月10日 星期一 20时58分47秒
> Description:LUOGU3388
************************************************************************/
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100005
struct node
{
int to;
int nex;
}E[N*2];
int n,m;
int head[N];
int par[N];
int low[N],dfn[N];
int cnt;
bool cut[N];//判断该点是否是割点
int dep;
int find_par(int x)
{
return x==par[x]?x:par[x]=find_par(par[x]);
}
void unite(int x, int y)
{
int fx=find_par(x);
int fy=find_par(y);
par[fy]=fx;
}
void addEdge(int a, int b)
{
E[cnt].to=b;
E[cnt].nex=head[a];
head[a]=cnt++;
E[cnt].to=a;
E[cnt].nex=head[b];
head[b]=cnt++;
}
void init()
{
memset(head,-1,sizeof(head));
memset(dfn,-1,sizeof(dfn));
cnt=dep=0;
for (int i=0; i<n; i++)
par[i]=i;
for (int i=0; i<m; i++)
{
int a,b;
scanf("%d%d",&a,&b);
addEdge(a-1,b-1);
unite(a-1,b-1);
}
}
void tarjan(int u, int fa)
{
low[u]=dfn[u]=dep++;
int child=0;
for (int k=head[u]; k!= -1; k=E[k].nex)
{
int v=E[k].to;
if (dfn[v]==-1)
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if (u==fa)
child++;
if (low[v]>=dfn[u]&&u!=fa)
cut[u]=true;
}
else if (v != fa)
low[u]=min(low[u],dfn[v]);
}
if (child>=2&&u==fa)
cut[u]=true;
}
void solve()
{
for (int i=0; i<n; i++)
{
if (par[i]==i)
{
tarjan(i,i);
}
}
int num=0;
for (int i=0; i<n ;i++)
if (cut[i])
num++;
printf("%d\n",num);
for (int i=0; i<n; i++)
if (cut[i])
printf("%d ",i+1);
printf("\n");
}
int main()
{
while (~scanf("%d%d",&n,&m))
{
init();
solve();
}
return 0;
}
路漫漫其修远兮,吾将上下而求索。