zoukankan      html  css  js  c++  java
  • 图论$cdot$强连通分量

    和无向图的连通分量类似,有向图有“强连通分量”的说法。“相互可达”的关系在有向图中也是等价关系。每一个集合称为有向图的一个强连通分量(scc)。如果把一个集合看成一个点,那么所有的scc构成了一个scc图。这个scc图不会存在任何有向环,因此是一个DAG。求解有向图强连通分量的算法一般都是基于dfs的,常用的算法有Kosaraju算法和Tarjan算法,下面给出Tarjan算法的代码:

     1 vector<int> G[maxn];
     2 int pre[maxn], low_link[maxn], scc_no[maxn], dfs_clk, scc_cnt;
     3 stack<int> S;
     4 void dfs(int u){
     5     pre[u] = low_link[u] = ++dfs_clk;
     6     S.push(u);
     7     FOR(i, 0, G[u].size() - 1){
     8         int v = G[u][i];
     9         if(!pre[v]){
    10             dfs(v);
    11             minimize(low_link[u], low_link[v]);
    12         }else if(!scc_no[v]) minimize(low_link[u], pre[v]);
    13     }
    14     if(low_link[u] == pre[u]){
    15         scc_cnt++;
    16         while(true){
    17             int x = S.top(); S.pop();
    18             scc_no[x] = scc_cnt;
    19             if(x == u) break;
    20         }
    21     }
    22 }
    23 void find_scc(int n){
    24     dfs_clk = scc_cnt = 0;
    25     clr(scc_no, 0), clr(pre, 0);
    26     FOR(i, 0, n - 1) if(!pre[i]) dfs(i);
    27 }

     由于每个点恰属于一个scc,因此我们希望在第一次访问某scc的结点并完成时就将该scc输出。所有需要判断某个点是否是其所在scc中最先被发现的点。与计算无向图bcc方法类似,对于每个结点$u$用$lowlink(u)$表示$u$及其后代能够追溯到最早的祖先点$v$的$pre(v)$的值。因此$u$是第一个被发现的点当且仅当$lowlink(u) =pre(u)$。

  • 相关阅读:
    BZOJ 4815: [Cqoi2017]小Q的表格
    BZOJ 3676: [Apio2014]回文串
    BZOJ 4503: 两个串
    BZOJ 2618: [Cqoi2006]凸多边形
    BZOJ 1137: [POI2009]Wsp 岛屿
    BZOJ 4824: [Cqoi2017]老C的键盘
    BZOJ 3167: [Heoi2013]Sao
    BZOJ 4033: [HAOI2015]树上染色
    1003. 我要通过!(20)
    1002. 写出这个数 (20)
  • 原文地址:https://www.cnblogs.com/astoninfer/p/5763195.html
Copyright © 2011-2022 走看看