图论-强连通分量

这是一份 Tarjan 求强连通分量的板子

其中和求割点,割边相同:
dfn[ ] 表示为时间戳数组
back[ ] 表示为能访问到的最远祖先(如果该祖先暂无SCC)


针对求解强联通分量,需要多定义如下变量

  1. stack<int> st; 用于存放 dfs 中的路径,从栈顶一直到 这个点本身(指 dfs 中 u)的点就是一个scc
  2. int sccno[ ]; 表示这个点属于第几个 scc

点击查看代码
int head[N], cnt;
struct Edge{
    int from, to, nxt;
}e[N << 1];
void add(int u, int v){
    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}

int ans_scc, sccno[N], dfn[N], back[N], tim;
stack<int> st;
void dfs(int u){
    st.push(u);
    dfn[u] = back[u] = ++tim;
    for(int i = head[u]; i != 0; i = e[i].nxt){
        int v = e[i].to;
        if(!dfn[v]){
            dfs(v);
            back[u] = min(back[u], back[v]);
        }else if(!sccno[v]){
            back[u] = min(back[u], dfn[v]);
            // back[u] = min(back[u], back[v]);
        }
    }
    if(back[u] == dfn[u]){
        ans_scc++;
        while(1){
            int v = st.top();
            st.pop();
            sccno[v] = ans_scc;
            if(u == v) break;
        }
    }
}

void Tarjan(int n){
    ans_scc = tim = 0;
    memset(sccno, 0, sizeof(sccno));
    memset(dfn, 0, sizeof(dfn));
    memset(back, 0, sizeof(back));
    for(int i = 1; i <= n; i++){
        if(!dfn[i])
            dfs(i);
    }
}

其中代码为

else if(!sccno[v]){
	back[u] = min(back[u], dfn[v]);
   // back[u] = min(back[u], back[v]);  这个也可以,与割点不同
}

有以下几点注意点:有以下几点注意点:

1. 在有向图中,back[i] 数组的意义更新了,现在一个点可以通过其祖先节点访问到更祖先的节点,结果显然成立,因为是有向图,并且求解问题不同。于是back[u] = min(back[u], back[v]);成立
2.笔者归结 Tarjan 的简化理解步骤2.笔者归结 Tarjan 的简化理解步骤
- 所有节点都想往上爬(将自己的能力提升),规定所有节点的能力只能依靠自己和子节点的能力,而不能依靠祖先节点的能力,证明也很显然,如果自己和儿子都不争气,不能连接到更先的父节点,那就只能自己成为一个 scc 了
- 当 dfs 到了节点 u 时,此时 u 为根节点,拓展下去一颗“树”,首先,大家起始的能力就是自己,当然“辈分越大,能力也越大”,当 dfs 到了节点 u 时,此时 u 为根节点,拓展下去一颗“树”,首先,大家起始的能力就是自己,当然“辈分越大,能力也越大”

于是,事情就变成了,所有节点都在期待一个突然爆发的子节点(或者靠本身),能使它本身连接到一个 dfn 最小的祖先节点。然后,针对节点 u ,
如果它与它子节点的努力得到了回报(指 back[u] < dfn[u]),那么递归返回到 u 时,就不用在 u 处更新一个新的 scc ,而在 u 的祖先节点处更新一个更大的 scc ;
如果(back[u] == dfn[u]),说明这个分支到此为止了,所有存在 stack 里的点都是这个 scc 的一员

posted @ 2024-05-10 16:48  9102700  阅读(27)  评论(0)    收藏  举报