int tol,head[maxn];
struct edge
{
int to,next;
bool cut;//是否为割边
}es[maxm];
void addedge( int u , int v )
{
es[tol].to = v;
es[tol].next = head[u];
es[tol].cut = false;
head[u] = tol++;
}
int Low[maxn],Dfn[maxn],Stack[maxn];
int Index,Top,Bridge,Add_block[maxn];//去掉此点原图变为几个连通子图
bool Instack[maxn],cut[maxn];//是否为割点
void dfs( int u , int f )
{
int v;
Low[u] = Dfn[u] = ++Index;
Stack[Top++] = u;
Instack[u] = true;
int son = 0;
for ( int i=head[u] ; i!=-1 ; i=es[i].next )
{
v = es[i].to;
if ( v==f ) continue;
if ( !Dfn[v] )
{
son++;
dfs( v , u );
if ( Low[u]>Low[v] )
Low[u] = Low[v];
if ( Low[v]>Dfn[u] )
{
Bridge++;
es[i].cut = true ;
es[i^1].cut = true;
}
if ( u!=f&&Low[v]>=Dfn[u] )
{
cut[u] = true;
Add_block[u]++;
}
}
else if ( Low[u]>Dfn[v] )
Low[u] = Dfn[v];
}
if ( u==f&&son>1 ) cut[u] = true;
if ( u==f ) Add_block[u] = son-1;
Instack[u] = false;
Top--;
}
void Tarjan_bridge()
{
memset ( Dfn , 0 , sizeof(Dfn) );
memset ( Instack , false , sizeof(Instack) );
memset ( Add_block , 0 , sizeof(Add_block) );
memset ( cut , false , sizeof(cut) );
Index = Top = Bridge = 0;
for ( int i=1 ; i<=n ; i++ )
if ( !Dfn[i] ) dfs( i , i );
}
void Tarjan_point()
{
memset ( Dfn , 0 , sizeof(Dfn) );
memset ( Instack , false , sizeof(Instack) );
memset ( Add_block , 0 , sizeof(Add_block) );
memset ( cut , false , sizeof(cut) );
Index = Top = Bridge = 0;
int cnt = 0;//原图连通块数目
for ( int i=1 ; i<=n ; i++ )
if ( !Dfn[i] ) dfs( i , i ),cnt++;
}