【双连通分量模板】


一、点双联通分量 O(n)

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 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]


二、边双连通分量 O(n)

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 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


你可能感兴趣的:(【模板集】-图论)