Tarjan(缩点,割点,桥)入门

Tarjan

在dfs的过程中记录时间戳与每个点可到达的时间戳最小的点
记:low当前可已过的时间戳最小的,dfn当前点的时间戳

缩点

顾名思义,缩点就是把一个强连通分量缩成一个点

inline void Tarjan(int x)// st栈,co当前点属于的强连通分量
{
    low[x]=dfn[x]=++cnt;
    st[++top]=x,vis[x]=1;
    for(re int i=h[x];i;i=e[i].ne)
    {
        int y=e[i].to;
        if(!dfn[y])
        {
            Tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if(vis[y])
            low[x]=min(low[x],dfn[y]);
    }
    if(low[x]==dfn[x])
    {
        ++color;
        while(st[top+1]!=x)
        {
            co[st[top]]=color;
            vis[st[top--]]=0;
        }
    }
}

割点

设该点为u,分为两种情况:
1.该点为根,且不止一个儿子
2.不为树根,该点的儿子v的low[v]>=dfn[u],(即v与v的子树无法通过任何边到达u以上)

inline void Tarjan(int u)
{
    low[u]=dfn[u]=++cnt;
    st[++top]=u,vis[u]=1;
    int son=0;
    for(re int i=h[u];i;i=e[i].ne)
    {
        int v=e[i].to;
        if(!dfn[v])
        {
            son++;
            Tarjan(v);
            low[u]=min(low[u],low[v]);
            if((u==root && son>1) || (u!=root && dfn[x]<=low[y])) flag[u]=1;
        }
        else if(vis[v])
            low[u]=min(low[u],dfn[v]);
    }
}

与求割点相似,low[v]>=dfn[u]时它们中间的边即为桥 (不贴代码了)

posted @ 2019-08-09 10:31  yzhx  阅读(859)  评论(0编辑  收藏  举报