图连通性模板

##有向图强连通缩点
####所需数组

i d x , l o w [ M A X N ] , d f n [ M A X N ] idx,low[MAXN],dfn[MAXN] ------------时间戳和两个访问标志
s c c n o , s c c [ M A X N ] sccno ,scc[MAXN] ————点属于哪个连通分支,及连通分量数量
s t a c k < i n t > s t , i n s t [ M A X N ] stack<int> st ,inst[MAXN] ————栈,一个中间工具,用于分辨点属于哪个连通分量
v e c t o r < i n t > G [ M A X N ] ; vector<int> G[MAXN]; ————图

const int N = 40000;
const int M = 500000;

int head[N];
int top;
int n,m;
struct Edge
{
    int val;
    int to;
    int next;
}edge[M];
void addedge(int a,int b,int c)
{
    edge[top].to=b;
    edge[top].val=c;
    edge[top].next=head[a];
    head[a]=top++;
}
void init()
{
    top=0;
    for (int i=1;i<=n;i++)  head[i]=-1;
}

int idx,low[N],dfn[N];
int sccno,scc[N];
stack<int>st; int inst[N];
void tarjan_init(){
    init();
    clr(dfn,0);
    clr(inst,0);
    clr(scc,0);
    sccno=idx=0;
    while(!st.empty()) st.pop();

}

void tarjan(int x)
{
    low[x]=dfn[x]=++idx;
    st.push(x);
    inst[x]=1;
    for(int i=head[x];~i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(!dfn[v]){
            tarjan(v);
            low[x]=min(low[v],low[x]);
        }
        else if(inst[v]){
            low[x]=min(low[x],dfn[v]);
        }
    }
    if(low[x]==dfn[x]){
        ++sccno;
        int v;
        while(1){
            v=st.top();
            st.pop();
            inst[v]=0;
            scc[v] = sccno;
            if(x==v) break;
        }
    }
}

##割边&&割点

//割点

const int N = 40000;
const int M = 500000;
int n,m;
int head[N];
int top;
struct Edge{
    int val;
    int to;
    int next;
}edge[M];
void addedge(int a,int b,int c)
{
    edge[top].to=b;
    edge[top].val=c;
    edge[top].next=head[a];
    head[a]=top++;
}
void init()
{
    top=0;
    for (int i=1;i<=n;i++)  head[i]=-1;
}
int low[N],dfn[N],idx;
int iscut[N];
int rootson;
void tarjan_init(){
    init();
    clr(dfn,0);
    idx=rootson=0;
    clr(iscut,0);

}


void tarjan(int u,int pre,int id){
    dfn[u]=low[u]=++idx;
    for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].to;
        if(i==(id^1)) continue;
        if(!dfn[v]){
            tarjan(v,u,i);
            if(u==1) rootson++;
            else {
                low[u]=min(low[u],low[v]);
                if(low[v]>=dfn[u]) iscut[u]=1;
            }
        }else{
            low[u]= min(low[u],dfn[v]);
        }
    }
}
if(rootson>1) iscut[1]=1;//调用后 加一句

//割边
const int N = 40000;
const int M = 500000;
int n,m;

int head[N];
int top;
struct Edge{
    int val;
    int to;
    int next;
}edge[M];
void addedge(int a,int b,int c){
    edge[top].to=b;
    edge[top].val=c;
    edge[top].next=head[a];
    head[a]=top++;
}
void init()
{
    top=0;
    clr(head,-1);
}
int low[N],dfn[N],idx;
int fa[N],isbridge[N];
int bridge;

void tarjan_init()
{
    init();
    clr(dfn,0);
    bridge=idx=0;
    clr(isbridge,0);
    clr(fa,0);
}

void tarjan(int u,int pre,int id){
    fa[u]=pre;
    low[u]=dfn[u]=++idx;
    for(int i=head[u];~i;i=edge[i].next){
        int v=edge[i].to;
        if(i==(id^1)) continue; //......
        if(!dfn[v]){
            tarjan(v,u,i);
            low[u]=min(low[u],low[v]);
            if(low[v] > dfn[u]) {
                isbridge[v]=1,bridge++;
                //cout<<"isbridge"<<endl;
            }
        }
        else if(v!=pre){ //。。。。。
            low[u]=min(low[u],dfn[v]);
        }
    }
}
//注意isbridge数组与fa数组一起用,且若isbridge[i],则i和fa[i]是割边
//重边要不要注意写法

割边割点注意=号

猜你喜欢

转载自blog.csdn.net/wyxxzsy/article/details/82496806