图联通模板(强连通,点双,边双)

本文提供图论中的关键算法模板,包括强连通分量、点双连通分量及边双连通分量的求解方法。通过Tarjan算法实现不同应用场景下的图结构分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

图联通模板全集

强连通模板

void tarjan(int x) {
    dfn[x]=low[x]=++tot;
    stk[++top]=x;
    vis[x]=1;//入栈标记
    for(int i=head[x]; i; i=G[i].nxt) {
        int y=G[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]) {
        int y;
        cnt++;//强连通分量个数
        do {
            y=stk[top--];
            vis[y]=0;//出栈去标记
            col[y]=cnt;//染色标记
        } while(y!=x);
    }
}

点双模板

求点双分量的点(方便造点方树,可以有重边)
void tarjan(int x) {
    dfn[x]=low[x]=++tot;
    stk[++Top]=x;
    int cnt=0;
    for(int i=head[x]; i; i=G[i].nxt) {
        int y=G[i].to;
        if(!dfn[y]) {
            cnt++;
            tarjan(y);
            low[x]=min(low[x],low[y]);
            if(low[y]>=dfn[x]) {
                mark[x]=1;//是割点
                BL[++blk].push_back(x);
                do {
                    BL[blk].push_back(stk[Top--]);
                } while(y!=stk[Top+1]);
            }
        } else {
            low[x]=min(low[x],dfn[y]);
        }
    }
    if(x==root&&cnt==1)mark[x]=0;//特殊情况不是割点
}
求点双的边和点(这份模板不能判重边)
void tarjan(int x,int f) {
    dfn[x]=low[x]=++tot;
    for(int i=head[x]; i; i=G[i].nxt) {
        int y=G[i].to;
        if(!dfn[y]) {
            stk[++Top].rd(x,y);
            tarjan(y);
            low[x]=min(low[x],low[y]);
            if(low[y]>=dfn[x]) {
                blk++;
                int a,b;
                do {
                    a=stk[Top].a;
                    b=stk[Top].b;
                    if(col[a]!=blk)col[a]=blk,BL[blk].push_back(a);
                    if(col[b]!=blk)col[b]=blk,BL[blk].push_back(b);
                    ADD(a,b);
                    Top--;
                } while(a!=x&&b!=y);
            }
        } else if(y!=f&&dfn[y]<dfn[x]) {
            stk[++Top].rd(x,y);
            low[x]=min(low[x],dfn[y]);
        }
    }
}

边双模板

求桥(可以有重边)
void tarjan(int x,int fa) {
    dfn[x]=low[x]=++tot;
    for(int i=head[x]; i; i=G[i].nxt) {
        int y=G[i].to;
        if(!dfn[y]) {
            tarjan(y,G[i].id);
            low[x]=min(low[x],low[y]);
            if(low[y]>dfn[x]) {
                mark[G[i].id]=1;
            }
        } else if(G[i].id!=fa) {
            low[x]=min(low[x],dfn[y]);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值