模板汇总——Tarjian

1. 单向边  + 新图建边

int belong[N], dfn[N], low[N], now_time, scc_cnt;
stack<int> s;
void dfs(int u){
    dfn[u] = low[u] = ++now_time;
    s.push(u);
    for(int i = head[u]; ~i; i = nt[i]){
        if(!dfn[to[i]]) dfs(to[i]);
        if(!belong[to[i]]) low[u] = min(low[u], low[to[i]]);
    }
    if(dfn[u] == low[u]){
        ++scc_cnt;
        int now;
        while(1){
            now = s.top(); s.pop();
            belong[now] = scc_cnt;
            if(now == u) break;
        }
    }
}
void scc(int n){
    now_time = scc_cnt = 0;
    for(int i = 1; i <= n; ++i)
        if(!belong[i]) dfs(i);
    int v;
    for(int i = 1; i <= n; ++i){
        for(int j = head[i]; ~j; j=nt[j]){
            v = to[j];
            if(belong[v] != belong[i]){
                    vc[belong[i]].pb(belong[v]);
            }
        }
    }
}
View Code

2.双向边 + 新图建边

int belong[N], dfn[N], low[N], now_time, scc_cnt;
vector<int> vc[N];
vector<pll> e[N];
stack<int> s;
void dfs(int u, int id){
    dfn[u] = low[u] = ++now_time;
    s.push(u);
    for(int i = head[u]; ~i; i = nt[i]){
        if(i == (id^1)) continue;
        if(!dfn[to[i]]) dfs(to[i], i);
        if(!belong[to[i]]) low[u] = min(low[u], low[to[i]]);
    }
    if(dfn[u] == low[u]){
        ++scc_cnt;
        int now;
        while(1){
            now = s.top(); s.pop();
            belong[now] = scc_cnt;
            if(now == u) break;
        }
    }
}
void scc(int n){
    for(int i = 1; i <= n; ++i) dfn[i] = low[i] = belong[i] = 0;
    while(!s.empty()) s.pop();
    now_time = scc_cnt = 0;
    for(int i = 1; i <= n; ++i)
        if(!belong[i]) dfs(i, -1);
    for(int i = 0, u, v; i < tot; i += 2){
        u = to[i], v = to[i+1];
        u = belong[u], v = belong[v];
        if(u != v) e[u].pb(pll(v,i/2+1)), e[v].pb(pll(u,i/2+1));
    }
}
View Code

3.边双连通分量。

  边双连通就是没有一个桥。

  桥的定义就是断开这个边能使得图分为2部分。

  先找到桥, 然后再dfs不经过桥所能到达的点都是同一个边双联通分量。  

int dfn[N], low[N], dtot;
void Tarjan(int o, int u){
    dfn[u]= low[u] = ++dtot;
    for(int i = head[u]; ~i; i = nt[i]){
        int v = to[i];
        if(!dfn[v]){
            Tarjan(u, v);
            low[u] = min(low[u], low[v]);
            if(low[v] > dfn[u])
                bridge[i] = bridge[i^1] = 1;
        }
        else if(v != o)
            low[u] = min(low[u], dfn[v]);
    }
}
int c[N], dcc;
void dfs(int u){
    c[u] = dcc;
    for(int i = head[u]; i; i = nt[i]){
        int v = to[i];
        if(c[v] || bridge[i]) continue;
        dfs(v);
    }
}
int ok[N];
vector<pll> vc[N];
void e_dcc(){
    for(int i = 1; i <= n; ++i)
        if(!dfn[i]) Tarjan(0, i);
    for(int i = 1; i <= n; ++i)
        if(!c[i]) {
            ++dcc;
            dfs(i);
        }
    for(int i = 0; i <= tot; i += 2){
        int u = to[i^1], v = to[i];
        u = c[u], v = c[v];
        if(u == v){
            ok[u] |= val[i];
        }
        else {
            vc[u].pb({v,val[i]});
            vc[v].pb({u,val[i]});
        }
    }
}
View Code
原文地址:https://www.cnblogs.com/MingSD/p/10097365.html