图论Tarjan求割点与桥

使用Tarjan方法计算割点与桥,这里先介绍下概念。

无向连通图中,如果删除某点后,图变成不连通,则称该点为割点。
无向连通图中,如果删除某边后,图变成不连通,则称该边为桥。

一个顶点u是割点,当且仅当满足(1)或(2)
(1) u为树根,且u有多于一个子树。

(2) u不为树根,且满足存在(u,v)为树枝边(或称父子边,即u为v在搜索树中的父亲),使得dfn(u)<=low(v)。
一条无向边(u,v)是桥,当且仅当(u,v)为树枝边,且满足dfn(u)


void Tarjan(int u, int father) //father 是u的父节点
{	
	Father[u] = father;
	int i,j,k;
	low[u] = dfn[u] = nTime ++;
	for( i = 0;i < G[u].size() ;i ++ ) {
		int v = G[u][i];
		if( ! dfn[v]) {
			Tarjan(v,u);
			low[u] = min(low[u],low[v]);
                        if(low[u]>low[u]) u,v为桥
 }
		else if( father != v ) //连到父节点的回边不考虑,否则求不出桥
			low[u] = min(low[u],dfn[v]);
	}
}
void Count()
{ //计算割点和桥
    int nRootSons = 0;    int i;
    Tarjan(1,0);
    for( i = 2;i <= n;i ++ ) {
        int v = Father[i];
        if( v == 1 )
            nRootSons ++; //DFS树中根节点有几个子树
        else {
            if( dfn[v] <= low[i])
                bIsCutVetext[v] = true;
        }
    }
    if( nRootSons > 1)
        bIsCutVetext[1] = true;
    for( i = 1;i <= n;i ++ )
        if( bIsCutVetext[i] )
            cout << i << endl;
    for( i = 1;i <= n;i ++) {
        int v = Father[i];
        if(v >0 &&  dfn[v] < low[i])
            cout << v << "," << i <


你可能感兴趣的:(图论)