http://blog.csdn.net/u011742541/article/details/14104613
int son,dfs_clock,low[maxn],dfn[maxn];
int iscut[maxn]; //iscut[i] 表示点i分割了几个连通分区
void dfs( int u,int fa )
{
low[u] = dfn[u] = ++dfs_clock;
for( int i = 0; i < map[u].size(); i ++ ){
int v = map[u][i];
if( !dfn[ v ] ){
dfs(v,u);
low[u] = low[u] <= low[v] ? low[u]:low[v];
if( low[v] >= dfn[u] ){
if( fa != -1 )
iscut[u] ++;
else
son ++;
}
}
else if( dfn[v] < dfn[u] && v != fa )
low[u] = low[u] <= dfn[v] ? low[u]:dfn[v];
}
}
void tarjan()
{
int ans = 0; //割点数
dfs_clock = 0,son = 0;
memset( low,0,sizeof(low) );
memset( dfn,0,sizeof(dfn) );
memset( iscut,0,sizeof(iscut) );
dfs(1,-1);
if( son > 1 ) //特判跟结点子树数
iscut[1] = son - 1;
for( int i = 1; i <= n; i ++ )
if( iscut[i] )
ans ++;
}