我发现了两种边双的写法
1.先求桥,标记桥再dfs求连通块,< 似乎有点麻烦
2.直接上有向图的写法,把回头的情况标记一下
其1
int tarjan(int x, int fa) { low[x] = dfn[x] = ++df; for (int i = head[x]; i; i = G[i].next) { int p = G[i].to; if (!dfn[p]) { tarjan(p, i); low[x] = min(low[x], low[p]); if (low[p] > dfn[x]) { aaa++; bri[i] = bri[i ^ 1] = 1; } } else if (fa == -1 || i != (fa ^ 1)) { low[x] = min(low[x], dfn[p]); } } return 0; } int dfss(int x) { clor[x] = ans; for (int i = head[x]; i; i = G[i].next) { int p = G[i].to; if (clor[p] || bri[i]) continue; dfss(p); } return 0; } ///// scanf("%d %lld", &n, &m); for (int i = 0; i < m; i++) { scanf("%d%d", &be, &en); insert(be, en); insert(en, be); } tarjan(1, -1); for (int i = 1; i <= n; i++) { if (!clor[i]) { ans++; dfss(i); } } ans 就是边双分量
其2.
int low[maxn], dfn[maxn], df, ans; int clor[maxn]; void insert(int be, int en) { G[be].push_back(en); } int tarjan(int x,int fa) { low[x] = dfn[x] = ++df; s.push(x); int flag=0; for (int i = 0; i < G[x].size(); i++) { int p = G[x][i]; if (p == fa){ flag++; if(flag == 1) continue;//和昆哥学的,标记回头,预防重边 } if (!dfn[p]) { tarjan(p, x); low[x] = min(low[x], low[p]); } else if (!clor[p]) { low[x] = min(dfn[p], low[x]); } } if (dfn[x] == low[x]) { ans++; while (1) { int a = s.top(); clor[a] = ans; s.pop(); if (a == x) break; } } return 0; } ////
原文:https://www.cnblogs.com/lesning/p/12111555.html