程式碼
點選檢視程式碼
int dfn[N], low[N], dfncnt, s[N], in_stack[N], tp;
int scc[N], sc; // 結點 i 所在 SCC 的編號
int sz[N]; // 強連通 i 的大小
void tarjan(int u) {
low[u] = dfn[u] = ++dfncnt, s[++tp] = u, in_stack[u] = 1;
for (int i = h[u]; i; i = e[i].nex) {
const int &v = e[i].t;
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (in_stack[v]) {
low[u] = min(low[u], dfn[v]);
}
}
if (dfn[u] == low[u]) {
++sc;
while (s[tp] != u) {
scc[s[tp]] = sc;
sz[sc]++;
in_stack[s[tp]] = 0;
--tp;
}
scc[s[tp]] = sc;
sz[sc]++;
in_stack[s[tp]] = 0;
--tp;
}
}
應用
我們可以將一張圖的每個強連通分量都縮成一個點。
然後這張圖會變成一個 DAG,可以進行拓撲排序以及更多其他操作。
舉個簡單的例子,求一條路徑,可以經過重複結點,要求經過的不同結點數量最多。