zoukankan      html  css  js  c++  java
  • 强连通分量SCC(Tarjan)

    什么叫强连通分量呢~

    有向图强连通分量在有向图G中,
    如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。
    如果有向图G的每两个顶点都强连通,称G是一个强连通图。
    有向图的极大强连通子图,称为强连通分量(strongly connected components)。

    举个例子:
    这里写图片描述

    一般来讲,我们选择的都是常数较小的线性算法:Tarjan

    实际上,学习过无向图的割点之后,
    SCC的tarjan算法更好理解

    tarjan ta老人家也是用dfs解决这个问题的
    考虑强连通分量C,设其阿红第一个被发现的点为x,
    则C中的其他点都是x的后代
    我们希望在x访问完成时立即输出C,现在问题的关键就是判断一个点是否是SCC中第一个被发现的点

    如图是一棵dfs树
    虚线表示一条或多条边
    这里写图片描述
    假设我们正在判断u是不是SCC中的第一个点,

    • 如果我们发现从u的子节点出发可以到达u的祖先w,显然u,v,w在一个SCC中
      因此u不是第一个发现的结点

    • 如果我们发现从v出发最多只能到达u,那么u就是SCC中第一发现的结点

    注意

    这里的到达,只能通过当前SCC中的点,而不能通过已经确定的SCC中的点

    很像无向图割点的low数组
    所以我们也可以用类似的方法维护出某一点能够到达的最早祖先

    附上一张图
    这里写图片描述

    vector<int> G[N],G2[N];
    stack<int> S;
    int tot,cnt,pre[N],cnt,low[N],scc[N];
    
    void dfs(int now)
    {
        pre[now]=low[now]=++tot;
        S.push(now);   //
        for (int i=0;i<G[now].size;i++)
        {
            int v=G[now][i];
            if (!pre[v])   //之前没有访问过
            {
                dfs(v);
                low[now]=min(low[now],low[v]);
            } 
            else if (!scc[v])   //ta不在之前得到的scc中
            {
                low[now]=min(low[now],pre[v]);
            } 
        }
        if (low[now]==pre[now])
        {
            cnt++;
            for(;;)
            {
                int x=S.top(); S.pop();
                scc[x]=cnt;
                if (x==now) break;
            }
        }
    }
    
    void find(int n)
    {
        cnt=0; tot=0;
        S.clear();
        memset(low,0,sizeof(low));
        memset(pre,0,sizeof(pre));
        for (int i=0;i<n;i++)
            if (!pre[i]) 
               dfs(i);
    }
  • 相关阅读:
    ionic入门之AngularJS扩展基本布局
    ionic入门之AngularJS扩展(一)
    test
    面试题小整理
    使用Code first 进行更新数据库结构(数据迁移)
    SQL模糊查询与删除多条语句复习
    GridView 根据要求显示指定值
    个人工作记录---工作中遇到的sql查询语句解析
    数据库,inner join,left join right join 的区别
    利用set实现去重
  • 原文地址:https://www.cnblogs.com/wutongtong3117/p/7673584.html
Copyright © 2011-2022 走看看