Tarjan连通性算法模板大整合

更新日志

前言

由于Tarjan算法页面过多,这里统一做一个整合,后期可能还会加入或者更改这里的模板。

另外的,这个页面只提供模板——以及链接,详细讲解点链接即可。

强连通

(有向图,储存每个节点属于的分量编号)

int scnt;
int scc[N],siz[N];
int dcnt;
int dfn[N],low[N];
bool ins[N];
stack<int> stk;
void tarjan(int rt){
    low[rt]=dfn[rt]=++dcnt;
    stk.push(rt);ins[rt]=true;
    for(int i=hd[rt];i;i=ne[i]){
        if(!dfn[to[i]]){
            tarjan(to[i]);
            low[rt]=min(low[rt],low[to[i]]);
        }
        else if(ins[to[i]])low[rt]=min(low[rt],dfn[to[i]]);
    }
    if(dfn[rt]==low[rt]){
        scnt++;
        while(true){
            int tp=stk.top();stk.pop();
            ins[tp]=false;
            scc[tp]=scnt;
            siz[scnt]++;
            if(tp==rt)break;
        }
    }
}

割点

(无向图,布尔数组判断割点+vector存储割点)

int dcnt;
int dfn[N],low[N];
bool flag[N];
veci spl;
void tarjan(int rt,int fa){
    dfn[rt]=low[rt]=++dcnt;
    int ccnt=0;flag[rt]=false;
    for(int e=hd[rt];e;e=ne[e]){
        int nxt=to[e];
        if(!dfn[nxt]){
            ccnt++;
            tarjan(nxt,rt);
            low[rt]=min(low[rt],low[nxt]);
            if(!flag[rt]&&low[nxt]>=dfn[rt]&&rt!=fa){
                spl.push_back(rt);
                flag[rt]=true;
            }
        }else low[rt]=min(low[rt],dfn[nxt]);
    }
    if(!flag[rt]&&rt==fa&&ccnt>=2){
        spl.push_back(rt);
        flag[rt]=true;
    }
}

割边

(无向图,布尔数组判断桥)

int dcnt;
int dfn[N],low[N];
bool bri[M];
void tarjan(int now,int fed){
    dfn[now]=low[now]=++cnt;
    for(int e=hd[now];e;e=ne[e]){
        int nxt=to[e],eid=(e-1)/2+1;
        if(!dfn[nxt]){
            tarjan(nxt,eid);
            low[now]=min(low[now],low[nxt]);
            if(low[nxt]>dfn[now]){
                bri[eid]=true;
            }
        }else if(eid!=fed)low[now]=min(low[now],dfn[nxt]);
    }
}

点双

(无向图,vector储存连通分量所有节点编号)

int dcnt;
int dfn[N],low[N];
bool flag[N];
stack<int> stk;
int bcnt;
vector<int> bcc[N];
void tarjan(int x,int fa){
    dfn[x]=low[x]=++dcnt;
    stk.push(x);
    int ccnt=0;
    for(int e=hd[x];e;e=ne[e]){
        int nxt=to[e];
        if(!dfn[nxt]){
            ++ccnt;
            tarjan(nxt,x);
            low[x]=min(low[x],low[nxt]);
            if(low[nxt]>=dfn[x]){
                ++bcnt;
                while(1){
                    int tp=stk.top();stk.pop();
                    bcc[bcnt].push_back(tp);
                    if(tp==nxt)break;
                }
                bcc[bcnt].push_back(x);
            }
        }else low[x]=min(low[x],dfn[nxt]);
    }
    if(x==fa&&ccnt==0){
        ++bcnt;
        bcc[bcnt].push_back(x);
    }
}

边双

(无向图,vector储存连通分量所有节点编号)

int dcnt;
int dfn[N],low[N];
int scnt;
vector<int> scc[N];
stack<int> stk;
void tarjan(int x,int fed){
    dfn[x]=low[x]=++dcnt;
    stk.push(x);
    for(int e=hd[x];e;e=ne[e]){
        int nxt=to[e];
        if(!dfn[nxt]){
            tarjan(nxt,(e-1)/2+1);
            low[x]=min(low[x],low[nxt]);
        }else if(fed!=(e-1)/2+1)low[x]=min(low[x],dfn[nxt]);
    }
    if(low[x]>=dfn[x]){
        ++scnt;
        while(1){
            int tp=stk.top();stk.pop();
            scc[scnt].push_back(tp);
            if(tp==x)break;
        }
    }
}
posted @ 2024-10-25 21:04  HarlemBlog  阅读(3)  评论(0编辑  收藏  举报