题面
【问题描述】
给你n个点及边的连接关系,求无向图的割点。N<=100
【输入】
有多组数据,第一行为n个点,接下来为多行(最多n行),每一行第一个为起点,后面紧跟着的为终点,起来和终点互相连同(如5 1 3 4,5和1连接,5和3连接,5和4连接),0表示这组数据结束。如果n为0表示程序结束。
【输出】
输出每组数据的割点数目。
【样例输入】
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
0
【样例输出】
1
2
算法分析
tarjan求割点模板题目。
参考程序
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
int n,ans,timee,root,low[110],dfn[110],point[110];
int fist[10100],to[10100],nex[10100],t;
void add(int x,int y)
{
to[++t]=y;
nex[t]=fist[x];
fist[x]=t;
return;
}
void tarjan(int u,int dad)
{
low[u]=dfn[u]=++timee;
int v,son=0;
for(int i=fist[u];i!=-1;i=nex[i])
{
v=to[i];
if(dfn[v]==0) //v的时间戳为0,表示未访问
{
son++;
tarjan(v,u);
low[u]=min(low[u],low[v]);
if((root==u&&son>=2)||(low[v]>=dfn[u]&&u!=root)) //割点满足条件
point[u]=1;
}
else if(v!=dad)
low[u]=min(low[u],dfn[v]);
}
return ;
}
int main()
{
while(scanf("%d",&n)&&n)
{
int u,v;
t=timee=ans=0;
memset(fist,-1,sizeof(fist)); //多组数据,需要初始化
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(point,0,sizeof(point));
while(scanf("%d",&u)&&u)
{
while(getchar()!='\n')
{
scanf("%d",&v);
add(u,v);
add(v,u);
}
}
for(int i=1;i<=n;i++)
if(dfn[i]==0) {root=i;tarjan(i,i);}
for(int i=1;i<=n;i++)
if(point[i]) ans++;
printf("%d\n",ans);
}
return 0;
}