割点就是缺失这个点后,联通分支增加。
/*
sample in
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0
sample out
1
2
*/
#include<stdio.h>
#include <string.h>
#define Max 0x7fffffff
int n,vis[100],pre[100],low[100],kids[100],cute[100],map[100][100];
//pre时用pre(u)记录u的访问时间,
//用low(u)数组记录u和u的子孙能追溯到的最早的节点(dfn值最小)。
//顶点u是割点当且仅当其满足(1)或者(2):
//(1) 若u是树根,且u的孩子数kids>1。因为没有u后,以这些孩子为根的子树间互相就不连通了,所以去掉u后得到kids个分支。
//(2) 若u不是树根,且存在树边(u,v)使 low(v)>=pre(u)。low值说明以v为根的子树不能到达u的祖先也就是去掉u后不能和原图联通,所以得到{这样的v的个数+1}个分支。
int min(int a,int b)
{
return a>b?b:a;
}
void dfs(int k,int deep)
{
int i;
pre[k]=low[k]=deep;
vis[k]=1;
for(i=1; i<=n; i++)
{
if(map[k][i]==1)
{
if(vis[i]==1)
{
low[k]=min(low[k],pre[i]);
}
else
{
kids[k]++;
dfs(i,deep+1);
low[k]=min(low[k],low[i]);
if(k==1&&kids[k]>1)
{
cute[k]=1;
}
else if(k!=1&&low[i]>=pre[k])
cute[k]=1;
}
}
}
}
int main()
{
int i,m,temp,sum;
char c;
while(scanf("%d",&n),n)
{
memset(vis,0,sizeof(vis));
memset(pre,0,sizeof(pre));
memset(kids,0,sizeof(kids));
memset(map,0,sizeof(map));
memset(cute,0,sizeof(cute));
for(i=0; i<100; i++)
low[i]=Max;
scanf("%d",&m);
while(m!=0)
{
while((c=getchar())!='\n')
{
scanf("%d",&temp);
map[m][temp]=map[temp][m]=1;
}
scanf("%d",&m);
}
dfs(1,1);
sum=0;
for(i=0; i<100; i++)
if(cute[i])sum++;
printf("%d\n",sum);
}
return 0;
}