网上比较多的版本是用vis数组来记录是否被访问过,其实不用也是可以的,只要预先把所有的dfn值都设为-1,便利的时候,如果遍历到dfn的值为-1的点,就说明是新的点,否则说明是老的点。
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <map>
#include <queue>
#include <stack>
#define N 105
#define INF 0x3f3f3f3f
using namespace std;
struct Edge{
int tar,next;
Edge(int a = 0,int b = 0){
tar = a,next = b;
}
}p[N*N];//从0开始计数
int low[N],dfn[N],head[N],vis[N];
bool rec[N];
int e,deep;//e用来表示边的个数
void addedge(int a,int b){
e++;
p[e] = Edge(b,head[a]);
head[a] = e;
}
void dfs(int u,int father)
{
int son=0;
vis[u]=1;
dfn[u]=low[u]=deep;
deep++;
for(int i=head[u]; i!=-1; i=p[i].next)
{
int v=p[i].tar;
if(dfn[v] == -1)
{
dfs(v,u);
son++;
low[u]=min(low[u],low[v]);
if((u==1&&son>1)||(u!=1&&dfn[u]<=low[v]))
rec[u]=1;
}else if( dfn[v] < dfn[father] && v != father){
low[u]=min(low[u],dfn[v]);
}
}
}
int n,m;
int main() {
int i,j,k,x;
while(scanf("%d",&m),m){
memset(p,0,sizeof(p));
memset(dfn,-1,sizeof(dfn));
memset(low,0,sizeof(low));
memset(head,-1,sizeof(head));
memset(rec,0,sizeof(rec));
memset(vis,0,sizeof(vis));
e=0,deep = 1;
while (scanf("%d",&n),n)
{
while (getchar() != '\n')
{
scanf("%d",&x);
addedge(n,x);addedge(x,n);
}
}
dfs(1,0);
int ans = 0;
for(i=1;i<=m;i++){
if(rec[i]){
ans++;
}
}
printf("%d\n",ans);
}
return 0;
}