割点的定义:如果k是割点,那么剩下的没有被访问过的点中至少会有一个点在不经过k点的情况下,无论如何再也回不到已访问过的点的~~
要完成这项工作需要两个数组num和low,num的下标是顶点编号,存储的是时间戳(即第几个被访问到的),low的下标是顶点编号,存储的是该定点在不经过父节点时,能够回到的最小时间戳(可以就是父节点),下面来了一个高大上的公式当v是u的子节点是,如果low[v]>=num[u],那么就不能回到祖先~~
#include <stdio.h>
int a[101][101];
int flag[101];
int num[101];
int low[101];
int index;
int root;
int n;
int min(int a,int b);
void dfs(int cur,int root);
int main()
{
int i,j,m,x,y;
scanf("%d%d",&n,&m);
for (i=1;i<=n;i++)
for (j=1;i<=n;i++)
a[i][j]=0;
for (i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
a[x][y]=1;
a[y][x]=1;
}
root=1;
index=0;
for (i=1;i<=n;i++)
flag[i]=0;
dfs(1,root);
for (i=1;i<=n;i++)
if (flag[i]==1)
printf("%d\n",i);
return 0;
}
int min(int a,int b)
{
return a<b?a:b;
}
void dfs(int cur,int father)
{
int child=0,i;
index++;
num[cur]=index;
low[cur]=index;
for (i=1;i<=n;i++)
{
if (a[i][cur]==1)
{
if (num[i]==0)//如果顶点i没有被访问过,那么cur一定是i的父节点
{
child++;
dfs(i,cur);
low[cur]=min(low[cur],low[i]);
if ((cur!=root)&&(low[i]>=num[cur]))//如果当前节点不是根节点并且符合关系式(为什么不是根节点,因为根节点就算low[i]>=num[cur]也不一定是割点,比如只有根节点1只有一个子节点2那么low[2]=1>=num[1],但是除去1节点后2节点孤立了,并不是割点(割点就是刨去取出的顶点后,剩下的顶点不能相互之间到达,取出1后,就剩本身,当然可以到达了)
flag[cur]=1;
if ((cur==root)&&(child==2))
flag[cur]=1;
}
else //如果顶点i被访问过了
if (i!=father)
{
low[cur]=min(low[cur],num[i]);
}
}
}
return;
}