【模板】tarjan


 【强连通分量,缩点】就是寻找环

int tarjan(int x){
    dfn[x]=low[x]=++tot;
    s.push(x);
    sta[x]=1;
    for(int i=last[x];i;i=a[i].next){//邻接表
        int y=a[i].to;
        if(dfn[y]==0){
            tarjan(y);
            low[x]=Min(low[x],low[y]);
        }
        else if(sta[y]==1) low[x]=Min(low[x],dfn[y]);
    }
    if(dfn[x]==low[x]){
        int k=0;
        Color++;
        while(x!=k){
            k=s.top();
            s.pop();
            sta[k]=0;
            color[k]=Color;
            num[Color]++;
        }
    }
    return 0;
}

 【割桥】

int tarjan(int x,int father){
    dfn[x]=low[x]=++tot;
    for(int i=last[x];i;i=a[i].next){
        int y=a[i].to;
        if(dfn[y]==0){
            tarjan(y,x);
            if(low[y]>dfn[x]){
                ans[++Ans].l=x;
                ans[Ans].r=y;
            }
            low[x]=Min(low[x],low[y]);
            continue;
        }
        else if(y!=father) low[x]=Min(low[x],dfn[y]);
    }
}

【割点】

int tarjan(int x,int father){
    int child=0;
    dfn[x]=low[x]=++tot;
    for(int i=last[x];i;i=a[i].next){
        int y=a[i].to;
        if(dfn[y]==0){
            tarjan(y,x);
            low[x]=Min(low[x],low[y]);
            if(low[y]>=dfn[x]){
                child++;
                if(child>1||root!=x) cut[x]=1;//不能直接存,会有重复点
            }
        }
        else if(y!=father) low[x]=Min(low[x],dfn[y]);
    }
}
int main(){
    (( ̄┰ ̄*)……)
    int Ans=0;
    for(int i=1;i<=n;i++)
        if(cut[i]==1) ans[++Ans]=i;
    printf("%d\n",Ans);
    for(int i=1;i<=Ans;i++) printf("%d ",ans[i]);
}

 

posted @ 2020-08-20 16:06  latent_Lin  阅读(121)  评论(0)    收藏  举报