• 模板汇总——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
  • 相关阅读:
    【转载】这是炎热小镇慵懒的一天
    【原创】Google的文本内容对比代码
    【原创】你知道Oracle 10G能存多少数据吗
    【原创】一个亿级数据库优化过程
    【原创】关于not in的一些事情
    【原创】自动结束进程脚本
    Android的线程使用来更新UI----Thread、Handler、Looper、TimerTask等
    Android 解决ListView 和 ScrollView 共存冲突的问题
    使用Symfony2的组件创建自己的PHP框架
    数据管理 ListView SQLite Dialog
  • 原文地址:https://www.cnblogs.com/MingSD/p/10097365.html
Copyright © 2020-2023  润新知