zoukankan      html  css  js  c++  java
  • 求强连通分量Tarjan算法

    int  dfn[16];       // 时间戳
    int  dfn_num = 0;   // 时间 
    int  low[16];       // 节点u所能访问到的最小时间戳 
    
    int inSt[16];       // 节点u是否在栈中.
    
    int st[16];
    int top = 0; 
    
    // 我们维护的信息.
    int col[16];        // 给节点染色, 同一个连通块的节点应该是同一个颜色的.
    int col_num = 0;    // 颜色值.
    int size[16];       // 每个颜色值所拥有的块数. 
    
    /*
     
    第一步:   访问当前节点的所有子节点:   子节点有三种 
        第一种:   未访问过的, 我们对它进行访问, 同时设置它的时间戳dfn[u]和low[u]为++ndfn_num,以及进栈.
        第二种:   访问过的,并且在栈中,我们直接更新我们 当前 节点的low[] --> 注意 应该用low[u] 和 dfn[v]比较. 
        第三种:   访问过的,并且不在栈中的, 我们直接跳过.因为这个时候,所以它已经染色了,属于一个连通块了. 
    第二步:   如果dfn[u] == low[u] 说明 已经找到一个连通块了.
              这时候我们要将栈顶元素弹出,直到当前节点. 记得也要修改inSt, 同时维护我们需要的信息. 
    */
    
    void Tarjan(int u) {
        int v, i;
        dfn[u] = low[u] = ++dfn_num; //添加时间戳. 
        st[++top] = u;      // 进栈 
        inSt[u] = true;     // 标示在栈 
        for (i=head[u]; i; i=edge[i].lst) {
            v = edge[i].to;
            if (!dfn[v]) {
                Tarjan(v);
                low[u] = min(low[u], low[v]);
            } else if (inSt[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if (dfn[u] == low[u]) { 
            col_num++;
            do {
                inSt[st[top]] = false;
                 col[st[top]] = col_num;
                 size[col_num]++;
            } while (st[top--] != u);
        }
    }

    简单数据 

    /*

    input: 

    6 8
    1 3
    3 5
    5 6
    4 6
    4 1
    1 2
    2 4
    3 4

    out:

    low : 1 1 3 1 6 4
    col : 3 3 3 3 2 1
    size: 1 1 4 0 0 0

    */

    板子题:  http://codevs.cn/problem/1332/

  • 相关阅读:
    汽车金融评分卡
    Lending Club 数据做数据分析&评分卡
    时间序列分析和预测 (转载)
    距离计算公式总结(转载)
    机器学习常用算法与辅助函数公式
    金融领域常用的数据分析方法
    常用模型评估方法总结
    A--集成算法的实现
    A--随机森林(RF)的 sciklit-learn 实现
    A--Scikit-Learn 实现决策树
  • 原文地址:https://www.cnblogs.com/cgjh/p/9554594.html
Copyright © 2011-2022 走看看