Advanced tarjan

Template to.

Scc previous studies, was almost hit backwards. Scc demand and shrinking point out is quite good (of course, will not really learn by points and edges).

Now learn a science seeking eDcc and vDcc of tarjan.

Seeking eDcc, seeking just have to learn bridge, then stained to dfs, as the contraction point is to enumerate each edge and create a new map.

The bridge is determined to be low [y]> dfn [x], because only then can not return to the position in the x dfs tree above. And due to some problems weight side, the second variable opening Tarjan, determines their low value is not updated, the adjacency list need to use pairs of conversion.

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
int read(){
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){
        if(x=='-') f=-1;
        x=getchar();
    }while(x>='0'&&x<='9'){
        sum=sum*10+x-'0';
        x=getchar();
    }return sum*f;
}
struct EDGE{
    int ed,nex;
}edge[100],edgec[100];
int first[50],firstc[50],num=1,numc;
int n,m;
int dfn[50],low[50],bl[50];
int ord,ecc;
bool bridge[100];
void add(int st,int ed){
    edge[++num].ed=ed;
    edge[num].nex=first[st];
    first[st]=first[st];
}
void addc(int st,int ed){
    edgec[++numc].ed=ed;
    edgec[numc].nex=firstc[st];
    firstc[st]=numc;
}
void tarjan(int x,int in_edge){
    dfn[x]=low[x]=++ord;
    for(int i=first[x];i;i=edge[i].nex){
        int y=edge[i].ed;
        if(!dfn[y]){
            tarjan(y);
            low[x]=min(low[x],low[y]);
            if(low[y]>dfn[x])
                bridge[i]=bridge[i^1]=1;
        }else if(i!=(in_edge^1))
            low[x]=min(low[x],dfn[y]);
    }
}
void dfs(int x){
    bl[x]=ecc;
    for(int i=first[x];i;i=edge[i].nex){
        int y=edge[i].ed;
        if(bl[y]||bridge[i]) continue;
        dfs(y);
    }
}
int main(){
    n=read();m=read();
    for(int i=1,x,y;i<=m;i++){
        x=read();y=read();
        add(x,y);add(y,x);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i]) tarjan(i,0);//求桥
    for(int i=1;i<=n;i++)
        if(!bl[i]){
            ecc++;
            dfs(i);
        }
    for(int i=2;i<=num;i++){
        int x=edge[i].ed,y=edge[i^1].ed;
        if(bl[x]==bl[y]) continue;
        addc(bl[x],bl[y]);
    }
}
View Code

VDCC seek, seeking to learn cut point, to put a sub-block stored in the vector by seeking VDCC cut vertex program.

Determining cut points to be low [y]> = dfn [x], and because of the nature of the search tree, the roots need to determine separately the situation.

Reduction point of time because of a cut point can be two vDcc, the first cut point so individually numbered, and then build a new edge.

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
struct EDGE{
    int ed,nex;
}edge[200],edgec[200];
int first[100],firstc[100];
int n,m,ord,top,root,vccnum,nvcn;
int dfn[100],low[100],sta[101000],new_id[100],bl[100];
vector<int>vcc[100];
bool cut[100];
int read(){
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){
        if(x=='-') f=-1;
        x=getchar();
    }while(x>='0'&&x<='9'){
        sum=sum*10+x-'0';
        x=getchar();
    }return sum*f;
}
void add(int st,int ed){
    edge[++num].ed=ed;
    edge[num].nex=first[st];
    first[st]=num;
}
void addc(int st,int ed){
    edgec[++numc].ed=ed;
    edgec[numc].nex=firstc[st];
    firstc[st]=numc;
}
void tarjan(int x){
    dfn[x]=low[x]=++ord;
    sta[++top]=x;
    if(root==x&&first[x]==0){
        vcc[++vccnum].push_back(x);
        return ;
    }
    int child=0;
    for(int i=first[x];i;i=edge[i].nex){
        int y=edge[i].ed;
        if(!dfn){
            tarjan(y);
            low[x]=min(low[x],low[y]);
            if(low[y]>=dfn[x]){
                child++;
                if((x==root&&child>=2)||(x!=root&&child>0)) cut[x]=1;
                vcc[++vccnum].push_back(x);
                int p;
                do{
                    p=sta[top--];
                    vcc[vccnum].push_back(p);
                }while(p!=y);
            }
        }else low[x]=min(low[x],dfn[y]);
    }
}
int main(){
    n=read();m=read();
    for(int i=1,x,y;i<=m;i++){
        x=read();y=read();
        add(x,y);add(y,x);
    }
    for(int i=1;i<=n;i++)
        if(!dfn[i]) root,tarjan(i);
    nvcn=vccnum;
    for(int i=1;i<=n;i++)
        if(cut[i]) new_id[i]=++nvcn;
    for(int i=1;i<=vccnum;i++)
        for(int j=0;j<vcc[i].size();j++){
            int x=vcc[i][j];
            if(cut[x]){
                addc(new_id[x],i);
                addc(i,new_id[x]);
            }else bl[x]=i;
        }
    
}
View Code

None of the above code tests, self-correct any errors.

Guess you like

Origin www.cnblogs.com/Yu-shi/p/11183312.html