割点,割桥,双联通模板总结

割点求法

void tarjan(int x,int fa)

{
    int temp,a,sum=0;
    low[x]=cnt[x]=++dfssum;
    for(a=0;a<edge[x].size();a++)
    {
        temp=edge[x][a];
        if(temp==fa)continue;//不能反向边
        if(!cnt[temp])
        {
            sum++;//记录儿子个数
            tarjan(temp,x);
            low[x]=min(low[x],low[temp]);
            if(x!=root&&low[temp]>=cnt[x])//注意是大于且等于
                iscut[x]=1;//当成为一条链的时候说明为断点
        }
        else low[x]=min(low[x],cnt[temp]);
    }
    if(x==root&&sum>1)iscut[x]=1;//儿子数大于一为断点;

}

桥的求法

void tarjan(int x,int fa)
{
    int temp;
    low[x]=cnt[x]=++dfssum;
    int sum=0;
    for(int a=head[x]; a!=-1; a=edge[a].next)
    {
        temp=edge[a].fina;
        if(temp==fa)continue;
        if(!cnt[temp])
        {
            tarjan(temp,x);
            low[x]=min(low[x],low[temp]);
            if(low[temp]>cnt[x])//注意是大于不等于
            {
                brige++;
                edge[a].cut=true;
                edge[a^1].cut=true;
            }
        }
        else if(low[x]>cnt[temp])
            low[x]=cnt[temp];
    }
}

边双联通

struct Edge{
    int u,v;
    Edge(int u=0,int v=0):u(u),v(v){}
}e[maxm];
int n,m,stamp,dfn[maxn],low[maxn],bccno[maxn],bcc_cnt;
vector
    
    
     
      vec[maxn],bcc[maxn];
bool g[maxn][maxn],isbridge[maxm];

void tarjan(int index,int fa)
{
    int tmp;
    dfn[index]=low[index]=++stamp;
    for(int i=0;i
     
     
      
      dfn[index])
                isbridge[vec[index][i]]=isbridge[vec[index][i]^1]=1;
        }
        else if(dfn[tmp]
      
      
     
     
    
    
点双联通

struct Edge{
    int u,v;
    Edge(int u=0,int v=0):u(u),v(v){}
}e[maxm];
int n,m,stamp,dfn[maxn],low[maxn],iscut[maxn],bccno[maxn];
int scnt,stack[maxm],bcc_cnt;
vector
     
     
      
       vec[maxn],bcc[maxn];

void tarjan(int index,int fa)
{
    int child=0,tmp;
    dfn[index]=low[index]=++stamp;
    for(int i=0;i
      
      
       
       =dfn[index])
            {
                iscut[index]=1;
                bcc[++bcc_cnt].clear();
                while(1)
                {
                    int num=stack[scnt--];
                    if(bccno[e[num].u]!=bcc_cnt)
                    {
                        bcc[bcc_cnt].push_back(e[num].u);
                        bccno[e[num].u]=bcc_cnt;
                    }
                    if(bccno[e[num].v]!=bcc_cnt)
                    {
                        bcc[bcc_cnt].push_back(e[num].v);
                        bccno[e[num].v]=bcc_cnt;
                    }
                    if(e[num].u==index && e[num].v==tmp)
                        break;
                }
            }
        }
        else if(dfn[tmp]
       
       
      
      
     
     



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值