比起双连通的Tarjan我倒是觉得反而简单多了。思想和双连通分量是同一个模式。
#include <cstdio> #include <cstring> #include <cstdlib> #include <stack> using namespace std; const int N = 1e5; int dfn[N], scc_id[N]; int deep, scc_cnt; stack <int> s; int dfs(int u) { int lowu = dfn[u] = ++deep; s.push(u); for(int i = head[u]; ~i; i = e[i].next) { int v = e[i].v; if(!dfn[v]) { int lowv = dfs(v); lowu = min(lowu, lowv); } else if(!scc_id[v]) {//连到栈中的还未标号的祖先们 lowu = min(lowu, dfn[v]); }//利用当前scc中的点来更新 } if(lowu == dfn[u]) {//只有最先发现的点满足这个条件 scc_cnt++; while(1) { int x = s.top(); s.pop(); scc_id[x] = scc_cnt; if(x == u) break; } } return lowu; } void tarjan() { for(int i = 0; i < n; i++) { dfn[i] = scc_id[i] = 0; } deep = scc_cnt = 0; for(int i = 0; i < n; i++) { if(!dfn[i]) dfs(i); } } int main() { return 0; }
时间: 2024-12-29 12:21:01