双连通分量模板

点双连通分量

1.调用init()初始化。用add(x,y)建边。然后调用find_vbcc();求解。
2.N,n是点数,M,m是边数。i和i^1互为反向边
3.belong表示该点属于哪一个联通分量(割顶无意义),bcc表示该联通分量的点(1~n),isc表示该点是否为割顶,bcc_cnt点双联通分支数量。
const int N=10010;
const int M=4000020;
struct edge
{
    int from,to,nex;
}e[M];
int head[M],dfn[N],low[N],belong[N],sta[N];
int n,m,nu,bcc_cnt,tim,top;
bool isc[N];
vector<int> bcc[N];
void add(int from,int to)
{
    e[nu].from=from;
    e[nu].to=to;
    e[nu].nex=head[from];
    head[from]=nu++;
}
void tarjan(int x,int fa)
{
    low[x]=dfn[x]=++tim;
    int child=0;
    for(int i=head[x];i+1;i=e[i].nex)
    {
        child++;
        int y=e[i].to;
        if(!dfn[y])
        {
            sta[++top]=i;
            tarjan(y,x);
            low[x]=min(low[x],low[y]);
            if(low[y]>=dfn[x])
            {
                isc[y]=true;
                 bcc_cnt++;bcc[bcc_cnt].clear();
                int tem1=0,tem2=0;
                while(true)
                {
                    edge ed=e[sta[top--]];
                    if(belong[ed.from]!=bcc_cnt)
               bcc[bcc_cnt].push_back(ed.from),belong[ed.from]=bcc_cnt;
                    if(belong[ed.to]!=bcc_cnt)
               bcc[bcc_cnt].push_back(ed.to),belong[ed.to]=bcc_cnt;
                    if(ed.from==x&&ed.to==y)break;
                }
            }
        }
        else if(dfn[y]<dfn[x]&&y!=fa)
        {
            low[x]=min(low[x],dfn[y]);
            sta[++top]=i;
        }
    }
    if(fa<0&&child==1)isc[x]=false;
}
void init()
{
    nu=0;
    memset(head,-1,sizeof(head));
}
void find_vbcc()
{
    memset(isc,false,sizeof(isc));
    memset(dfn,0,sizeof(dfn));
    memset(belong,0,sizeof(belong));
    top=tim=bcc_cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        tarjan(i,-1);
    }
}

边双连通分量模板:

1.调用init()初始化,用add(x,y)添加一条边,然后调用find_ebcc(),如果需要缩点建树就suodian();
2.N,n是点数,M,m是边数。下标1-n
3.bcc_cnt是联通分量数,g是所点后建的无根树。第i条边和第i^1条边是互为反向边
const int N=10010;
const int M=200020;
int head[M],dfn[N],low[N],du[N],belong[N];
int n,m,nu,bcc_cnt,tim;
bool isb[M];
vector<int> g[N];
struct edge
{
    int from,to,nex;
}e[M];
void add(int from,int to)
{
    e[nu].from=from;
    e[nu].to=to;
    e[nu].nex=head[from];
    head[from]=nu++;
}
void tarjan(int x,int fa)
{
    low[x]=dfn[x]=++tim;
    for(int i=head[x];i+1;i=e[i].nex)
    {
        int y=e[i].to;
        if((i^1)==fa)continue;
        if(!dfn[y])
        {
            tarjan(y,i);
            low[x]=min(low[x],low[y]);
            if(low[y]>dfn[x])
            {
                isb[i]=isb[i^1]=true;
            }
        }
        else
        low[x]=min(low[x],dfn[y]);
    }
}
void dfs(int x)
{
    belong[x]=bcc_cnt;
    for(int i=head[x];i+1;i=e[i].nex)
    {
        int y=e[i].to;
        if(belong[y]||isb[i])continue;
        dfs(y);
    }
}
void init()
{
    nu=0;
    memset(head,-1,sizeof(head));
    memset(du,0,sizeof(du));
}
void find_ebcc()
{
    memset(dfn,0,sizeof(dfn));
    memset(isb,false,sizeof(isb));
    tim=bcc_cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i])
        tarjan(i,-1);
    }
    memset(belong,0,sizeof(belong));
    for(int i=1;i<=n;i++)
    {
        if(!belong[i])
         {   bcc_cnt++;
             dfs(i);
         }
    }
}
void suodian()
{
    for(int i=1;i<=bcc_cnt;i++)g[i].clear();
    for(int i=0;i<nu;i+=2)
    {
        int x=belong[e[i].from],y=belong[e[i].to];
        if(x==y)continue;
        g[x].push_back(y);
        g[y].push_back(x);
        du[x]++;
        du[y]++;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值