zoukankan      html  css  js  c++  java
  • 强连通(当模板用)——pku2186Popular Cows

    有向图强连通分量的Tarjan算法

    有个比较好的讲解http://www.byvoid.com/blog/scc-tarjan/zh-hans/

    学习一下,贴个比较好的模板

    View Code
    #include <iostream>
    #include
    <stack>
    using namespace std;

    const int MAXN = 10000 + 10; // 点的最大数量
    const int MAXM = 50000 + 10; // 边的最大数量

    // 假设对边u-->v
    struct EDGE
    {
    int v; // 从u点出发能到达的点v
    int next; // 从u点出发能到达的下一条边的编号
    };

    stack
    <int> s;
    EDGE map[MAXM];
    int low[MAXN]; // low[u]:是u或u的子树能够追溯到的最早的栈中节点的次序号
    int dfn[MAXN]; // dfn[u]:节点u搜索的次序编号(时间戳)
    int pre[MAXN]; // pre[u] = e:从点u出发的最后一条边的编号是e(“最后”是指最后输入)
    int sccf[MAXN]; // sccf[i] = j:第i个点所在的强连通分量的编号
    bool ins[MAXN]; // 是否在栈中
    int outdegree[MAXN]; // 强连通分量的出度
    int index; // 次序编号
    int scc; // 强连通分量的数目
    int n, m;

    void Tarjan(int u)
    {
    int v;
    low[u]
    = dfn[u] = index++;
    s.push(u);
    ins[u]
    = true;
    // 枚举每一条边:u-->v
    for (int k=pre[u]; k!=-1; k=map[k].next)
    {
    v
    = map[k].v;
    if (dfn[v] == 0)
    {
    Tarjan(v);
    if (low[v] < low[u])
    {
    low[u]
    = low[v];
    }
    }
    else if (ins[v] && dfn[v]<low[u])
    {
    low[u]
    = dfn[v];
    }
    }
    // 如果节点u是强连通分量的根
    if (dfn[u] == low[u])
    {
    scc
    ++;
    do
    {
    v
    = s.top();
    s.pop();
    ins[v]
    = false;
    sccf[v]
    = scc;//这里就是一个缩点的过程
    }while (u != v);
    }
    }

    void Init()
    {
    scc
    = 0;
    index
    = 1;
    memset(low,
    0, sizeof(low));
    memset(dfn,
    0, sizeof(dfn));
    memset(ins,
    false, sizeof(ins));
    memset(sccf,
    0, sizeof(sccf));
    memset(pre,
    -1, sizeof(pre));
    }

    // 获得超级受喜欢的cows的数量
    int GetSuperPopularNum()
    {
    int u, v;
    int cnt = 0; // 出度为0的强连通分量的数目
    int ct[MAXN]; // ct[i] = j:强连通分量i有j个点

    memset(outdegree,
    0, sizeof(outdegree));
    memset(ct,
    0, sizeof(ct));

    // 枚举每一个点u:求outdegree和ct
    for (u=1; u<=n; u++)
    {
    ct[sccf[u]]
    ++;
    for (int k=pre[u]; k!=-1; k=map[k].next)
    {
    // 对每条边u-->v
    v = map[k].v;
    if (sccf[u] != sccf[v])
    {
    outdegree[sccf[u]]
    ++;
    }
    }
    }
    // 数数强连通分量为0的点有多少个
    for (u=1; u<=scc; u++)
    {
    if (outdegree[u] == 0)
    {
    cnt
    ++;
    v
    = u;
    }
    }
    return (cnt == 1)? ct[v] : 0;
    }

    int main()
    {
    int i, u, v;
    int e = 0; // 边的数量,建图时会用到
    // 初始化数据并建图
    Init();
    //cin >> n >> m;
    scanf("%d%d",&n,&m);
    for (i=0; i<m; i++)
    {
    //cin >> u >> v;
    scanf("%d%d",&u,&v);
    map[e].v
    = v;
    map[e].next
    = pre[u];
    pre[u]
    = e;
    e
    ++;
    }
    // 求强连通分量
    for (i=1; i<=n; i++)
    {
    if (dfn[i] == 0)
    {
    Tarjan(i);
    }
    }
    // 输出答案
    cout << GetSuperPopularNum() << endl;
    return 0;
    }

      

  • 相关阅读:
    $.cookie 使用不了的问题定位过程
    jquery.cookie.js使用介绍
    java 转换 小函数(不断增加中。。。)
    jquery ajax 访问webServer的xml文件
    JS中的prototype【转】
    【转载】习惯决定性格 性格决定命运
    jquery的ajax和原始的ajax这两种方式的使用方法
    ajax readyState的五种状态详解
    一个简单的tcp代理实现
    go tcp使用
  • 原文地址:https://www.cnblogs.com/huhuuu/p/2121148.html
Copyright © 2011-2022 走看看