题目链接:http://poj.org/problem?id=1144
判断割点:
(1)u的子节点不能回到dfs中u的父节点 即dfn[u]<=low[v]
(2)根节点特判,有两个及以上的子节点即可。
#include<cstdio>
#include<cstring>
using namespace std;
const int N=105;
int head[N],dfn[N],low[N],fa[N],e,n,cnt,cut[N],ans;
struct node
{
int u,next;
}edge[3005];
int min(int a,int b)
{
if(a<b)
return a;
return b;
}
void add(int a,int b)
{
edge[e].u=b;
edge[e].next=head[a];
head[a]=e++;
}
void init()
{
e=0;cnt=1;ans=0;
memset(dfn,-1,sizeof(dfn));
memset(head,-1,sizeof(head));
memset(fa,0,sizeof(fa));
memset(cut,0,sizeof(cut));
}
void Tarjan(int a,int father)
{
int i,v;
dfn[a]=low[a]=cnt++;
fa[a]=father;
for (i=head[a];i!=-1;i=edge[i].next)
{
v=edge[i].u;
if (dfn[v]==-1)
{
Tarjan(v,a);
low[a]=min(low[a],low[v]);
}
else low[a]=min(low[a],dfn[v]);
}
}
void Count()
{
int i,rtn=0,v;
Tarjan(1,0);
for(i=2;i<=n;i++)
{
v=fa[i];
if(v==1)
rtn++;
else
if(dfn[v]<=low[i])
cut[v]=1;
}
if(rtn>1)
ans++;
for(i=1;i<=n;i++)
if(cut[i])
ans++;
}
int main()
{
int a,b,i;
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
init();
while(scanf("%d",&a)&&a)
{
while(getchar()!='\n')
{
scanf("%d",&b);
add(a,b);
add(b,a);
}
}
Count();
printf("%d\n",ans);
}
return 0;
}