模板汇总——Tarjian
1. 单向边 + 新图建边
int belong[N], dfn[N], low[N], now_time, scc_cnt; stack<int> s; void dfs(int u){ dfn[u] = low[u] = ++now_time; s.push(u); for(int i = head[u]; ~i; i = nt[i]){ if(!dfn[to[i]]) dfs(to[i]); if(!belong[to[i]]) low[u] = min(low[u], low[to[i]]); } if(dfn[u] == low[u]){ ++scc_cnt; int now; while(1){ now = s.top(); s.pop(); belong[now] = scc_cnt; if(now == u) break; } } } void scc(int n){ now_time = scc_cnt = 0; for(int i = 1; i <= n; ++i) if(!belong[i]) dfs(i); int v; for(int i = 1; i <= n; ++i){ for(int j = head[i]; ~j; j=nt[j]){ v = to[j]; if(belong[v] != belong[i]){ vc[belong[i]].pb(belong[v]); } } } }
2.双向边 + 新图建边
int belong[N], dfn[N], low[N], now_time, scc_cnt; vector<int> vc[N]; vector<pll> e[N]; stack<int> s; void dfs(int u, int id){ dfn[u] = low[u] = ++now_time; s.push(u); for(int i = head[u]; ~i; i = nt[i]){ if(i == (id^1)) continue; if(!dfn[to[i]]) dfs(to[i], i); if(!belong[to[i]]) low[u] = min(low[u], low[to[i]]); } if(dfn[u] == low[u]){ ++scc_cnt; int now; while(1){ now = s.top(); s.pop(); belong[now] = scc_cnt; if(now == u) break; } } } void scc(int n){ for(int i = 1; i <= n; ++i) dfn[i] = low[i] = belong[i] = 0; while(!s.empty()) s.pop(); now_time = scc_cnt = 0; for(int i = 1; i <= n; ++i) if(!belong[i]) dfs(i, -1); for(int i = 0, u, v; i < tot; i += 2){ u = to[i], v = to[i+1]; u = belong[u], v = belong[v]; if(u != v) e[u].pb(pll(v,i/2+1)), e[v].pb(pll(u,i/2+1)); } }
3.边双连通分量。
边双连通就是没有一个桥。
桥的定义就是断开这个边能使得图分为2部分。
先找到桥, 然后再dfs不经过桥所能到达的点都是同一个边双联通分量。
int dfn[N], low[N], dtot; void Tarjan(int o, int u){ dfn[u]= low[u] = ++dtot; for(int i = head[u]; ~i; i = nt[i]){ int v = to[i]; if(!dfn[v]){ Tarjan(u, v); low[u] = min(low[u], low[v]); if(low[v] > dfn[u]) bridge[i] = bridge[i^1] = 1; } else if(v != o) low[u] = min(low[u], dfn[v]); } } int c[N], dcc; void dfs(int u){ c[u] = dcc; for(int i = head[u]; i; i = nt[i]){ int v = to[i]; if(c[v] || bridge[i]) continue; dfs(v); } } int ok[N]; vector<pll> vc[N]; void e_dcc(){ for(int i = 1; i <= n; ++i) if(!dfn[i]) Tarjan(0, i); for(int i = 1; i <= n; ++i) if(!c[i]) { ++dcc; dfs(i); } for(int i = 0; i <= tot; i += 2){ int u = to[i^1], v = to[i]; u = c[u], v = c[v]; if(u == v){ ok[u] |= val[i]; } else { vc[u].pb({v,val[i]}); vc[v].pb({u,val[i]}); } } }