The analysis for USACO Platinum Disruption mentions a $O(m\alpha(n))$ solution. Although this is not a two-connected component problem, we can in fact use DSU to generate two-connected components.
(explanation?)
<spoiler title="Code">
The DSU operations take $O(\log n)$ rather than $O(\alpha(n))$ because the DSU does not use union by size, but it's easy to change this.
```cpp
struct TwoEdgeCC {
struct {
vi e; void init(int n) { e = vi(n,-1); }
int get(int x) { return e[x] < 0 ? x : e[x] = get(e[x]); }
bool unite(int x, int y) { // set par[y] = x
x = get(x), y = get(y); if (x == y) return 0;
e[x] += e[y]; e[y] = x; return 1;
}
} DSU;
int N; vector<vi> adj; vi depth, par;
vpi extra;
void init(int _N) {
N = _N; DSU.init(N);
adj.rsz(N), depth.rsz(N), par = vi(N,-1);
}
void dfs(int x) {
trav(t,adj[x]) if (t != par[x])
par[t] = x, depth[t] = depth[x]+1, dfs(t);
}
void ae(int a, int b) {
if (DSU.unite(a,b)) adj[a].pb(b), adj[b].pb(a); // tree edge