Descubra todos los puentes, luego retire el puente
#include <cstdio> #include <iostream> usando el espacio de nombres std; const int MAXN = 1e5, MAXM = 1e6; struct Edge { int de, a, nxt; } e [MAXM]; int head [MAXN], edgeCnt = 1; addEdge vacío (int u, int v) { e [++ edgeCnt] .from = u; e [edgeCnt] .to = v; e [edgeCnt] .nxt = cabeza [u]; head [u] = edgeCnt; } int dfn [MAXN], bajo [MAXN], dfnCnt = 0; puente de bool [MAXM]; nulo tarjan (int x, int in_edge) { dfn [x] = bajo [x] = ++ dfnCnt; for (int i = head [x]; i; i = e [i] .nxt) { int nowV = e [i] .to; if (! dfn [nowV]) { tarjan (nowV, i); if (bajo [nowV]> dfn [x]) { bridge [i] = bridge [i ^ 1] = 1; } low [x] = min (low [x], low [nowV]); } else if (i! = (in_edge ^ 1)) { low [ x] = min (bajo [x], dfn [nowV]); } } } int inDcc [MAXN]; void dfs (int x, int nowDcc) { inDcc [x] = nowDcc; // El punto X es nowd Este lado se duplica para (int i = head [x]; i; i = e [i] .nxt) { int nowV = e [i] .to; if (inDcc [nowV] || bridge [i]) / / Si se ha atribuido a un par de lados, o el primer lado es un puente, continúe; dfs (nowV, nowDcc); } } int main () { int n, m; scanf ("% d% d", & n, & m); para (int i = 1; i <= m; i ++) { int u, v; scanf ("% d% d", & u, & v); addEdge (u, v); addEdge (v, u); } para (int i = 1; i <= n; i ++) // Buscar todos los puentes Fuera si (! Dfn [i]) tarjan (i, 0); int nowDcc = 0; for (int i = 1; i <= n; i ++) // si el punto no se ha asignado a un lado determinado if ( ! inDcc [i]) dfs (i, ++ nowDcc); printf ("% d \ n", nowDcc); return 0; }