题目:http://poj.org/problem?id=1144
Tarjan无向图求割点。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
using namespace std;
#define Maxn 105
#define Maxm 10005
struct Edge
{
int a,b;
}edge[Maxm];
int first[Maxn];
int next[Maxm];
int total;
//割点相关
int dfn[Maxn];
int low[Maxn];
int iscut[Maxn];
int dfs_clock;
int root;
void addEdge(int a,int b)
{
edge[total].a = a,edge[total].b = b;
next[total] = first[a];
first[a] = total++;
}
void tarjan(int u)
{
dfn[u] = low[u] = ++dfs_clock;
int cnt = 0;
for(int i=first[u];i!=-1;i=next[i])
{
int v = edge[i].b;
if(!dfn[v])
{
tarjan(v);
cnt++;
low[u] = min(low[u],low[v]);
if( (u == root && cnt>1) || (u!=root && dfn[u]<=low[v]) )
{
iscut[u] = true;
}
}
else
{
low[u] = min(low[u],dfn[v]);
}
}
}
int cutPoint(int n)
{
dfs_clock = 0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(iscut,false,sizeof(iscut));
//如果是非连通图,就得用for循环了
//如果是连通图,root=1,tarjan(1)即可
for(int i=1;i<=n;i++)
{
if(!dfn[i]) root = i,tarjan(i);
}
int ans = 0;
for(int i=1;i<=n;i++)
{
if(iscut[i]) ans++;
}
return ans;
}
void init()
{
total = 0;
memset(first,-1,sizeof(first));
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n;
int u,v;
char c;
while(scanf(" %d",&n)!=EOF)
{
if(n == 0) break;
init();
while(scanf(" %d",&u)!=EOF && u!=0)
{
while(scanf("%c",&c) && c!='\n')
{
scanf("%d",&v);
addEdge(u,v);
addEdge(v,u);
}
}
int ans = cutPoint(n);
printf("%d\n",ans );
}
return 0;
}