Tarjan求割点

1 篇文章 0 订阅
1 篇文章 0 订阅

模板题:luogu3388

题面:
给出一个n个点,m条边的无向图,求图的割点。

思路:
对于每一个没有访问过(dfn[n]==0)的顶点,用tarjan算法以此点为根生成一颗dfs树
这里写图片描述
low记录与该节点连接的dfs序最小的节点的dfs序(时间戳),dfn则记录该节点的dfs序。
当第一个节点回溯到其父节点时,若low[son]>dfn[father],说明该子节点不与任何在以该子节点为根的子树外的节点连接,则该父节点一定为割点;若low[son]

...
int son=0, back=0;
void tarjan(int u, int rt)
{
    dfn[u]=++tim; low[u]=tim;
    instack[u]=true;
    sta.push(u);

    for(int i=front[u]; i>0; i=e[i].next)
    {
        int v=e[i].v; fa[v] = u;

        if(u==rt) son++;
        if(v==rt && fa[u]!=rt) back++;
        //更新son和back

        if(dfn[v]==0)
        {
            fa[v]=u;
            tarjan(v, rt);
            low[u]=min(low[u], low[v]);
            if(low[v]>=dfn[u] && u!=rt && inq[u]==false) //如果一个非根节点满足low[father]>=dfn[son]且之前没有入队
            {
                q.push(u);
                inq[u] = true;
                ans++;
            }
        }
        if(instack[u]==true) low[u]=min(low[u], dfn[v]);
    }

    if(u==rt && (son-back<=1 || son<=1)) iscut[rt]=false; //判断根节点是否为割点

    instack[u]=false;
    sta.pop();
}

int main()
{
    ...
    for(int i=1; i<=n; i++)
    {
        if(dfn[i]!=0) continue;
        iscut[i]=true; 
        son=0, back=0;
        tarjan(i, i);
        if(iscut[i]==false || inq[i]==true) continue; //如果根节点不是割点或者根节点已经入队, 则跳过
        inq[i] = true;
        q.push(i);
        ans++;
        break;
    }
    ...
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值