无向图边双连通分量
第一遍DFS找出所有桥,第二遍DFS,给边连通分量标号。
模板:
#include <bits/stdc++.h> using namespace std; const int maxn = 20005; int dfn[maxn],low[maxn],tot; vector<int> g[maxn]; bool isB[maxn][maxn]; int n,m; //找到桥 void tarjan(int u,int fa) { dfn[u] = low[u] = ++tot; for(int i = 0; i < (int)g[u].size(); i++) { int v = g[u][i]; if(!dfn[v]) { tarjan(v,u); low[u] = min(low[u],low[v]); if(low[v]>dfn[u]) isB[u][v] = isB[v][u] = true; } else if(fa!=v) { low[u] = min(low[u],dfn[v]); } } } //边双连通标号 int bcc_cnt; int bccno[maxn]; void dfs(int idx) { dfn[idx] = 1; bccno[idx] = bcc_cnt; for(int i = 0; i < (int)g[idx].size(); i++) { int v = g[idx][i]; if(isB[idx][v]) continue; if(!dfn[v]) dfs(v); } } void find_ebcc() { bcc_cnt = tot = 0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(bccno,0,sizeof(bccno)); memset(isB,0,sizeof(isB)); for(int i = 1; i <= n; i++) { if(!dfn[i]) { tarjan(i,-1); } } memset(dfn,0,sizeof(dfn)); for(int i = 1; i <= n; i++) { if(!dfn[i]) { bcc_cnt++; dfs(i); } } } int main() { freopen("in.txt","r",stdin); scanf("%d%d",&n,&m); for(int i = 0; i < m; i++) { int u,v; scanf("%d%d",&u,&v); g[u].push_back(v); g[v].push_back(u); } find_ebcc(); puts(""); return 0; }
这一份模板最类似于lrj的风格了,网上也有一篇,但是有明显bug!!!