// O(m^3) #include <bits/stdc++.h> using std::vector; void init_io() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); } struct Vertex; struct Edge { Vertex *dest; size_t edge_idx; bool on = true; }; struct Vertex { vector<Edge> edges; int depth = -1; int low = -1; }; vector<Vertex> vertices; vector<std::array<std::pair<Vertex*, size_t>, 2>> edge_ptrs; void read_input() { size_t num_vertices, num_edges; std::cin >> num_vertices >> num_edges; vertices.resize(num_vertices); edge_ptrs.reserve(num_edges); for (size_t edge_idx=0; edge_idx<num_edges; ++edge_idx) { size_t a, b; std::cin >> a >> b; --a; --b; Vertex *va = &vertices[a]; Vertex *vb = &vertices[b]; std::array<std::pair<Vertex*, size_t>, 2> ep; for (int i=0; i<2; ++i) { Edge edge; edge.dest = vb; edge.edge_idx = edge_idx; ep[i].first = va; ep[i].second = va->edges.size(); va->edges.push_back(edge); std::swap(a, b); std::swap(va, vb); } edge_ptrs.push_back(ep); } } void set_edge_on(const size_t edge_idx, bool on) { for (const auto [v, i] : edge_ptrs[edge_idx]) { v->edges[i].on = on; } } size_t g_min_bridge_idx; size_t g_visited_vertices; size_t g_num_bridges; void biconnected_components(Vertex *v, size_t parent_edge, int depth) { ++g_visited_vertices; v->depth = depth; v->low = depth; for (const Edge &edge : v->edges) { if (edge.edge_idx == parent_edge || !edge.on) continue; Vertex *w = edge.dest; const int d = w->depth; if (d == -1) { biconnected_components(w, edge.edge_idx, depth+1); if (w->low >= depth+1) { g_num_bridges += edge.edge_idx >= g_min_bridge_idx; } else { v->low = std::min(v->low, w->low); } } else { v->low = std::min(v->low, d); } } } size_t count_disconnecting_edges(size_t min_bridge_idx) { for (Vertex &v : vertices) { v.depth = -1; v.low = -1; } g_min_bridge_idx = min_bridge_idx; g_visited_vertices = 0; g_num_bridges = 0; biconnected_components(&vertices[0], edge_ptrs.size(), 0); if (g_visited_vertices == vertices.size()) { return g_num_bridges; } else { return edge_ptrs.size() - g_min_bridge_idx; } } uint64_t solve() { uint64_t res = 0; for (size_t edge0 = 0; edge0 < edge_ptrs.size(); ++edge0) { set_edge_on(edge0, false); for (size_t edge1 = edge0+1; edge1 < edge_ptrs.size(); ++edge1) { set_edge_on(edge1, false); const auto c = count_disconnecting_edges(edge1+1); set_edge_on(edge1, true); res += c; } set_edge_on(edge0, true); } return res; } int main() { init_io(); read_input(); const auto res = solve(); std::cout << res << "\n"; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | // O(m^3) #include <bits/stdc++.h> using std::vector; void init_io() { std::cin.tie(nullptr); std::ios::sync_with_stdio(false); } struct Vertex; struct Edge { Vertex *dest; size_t edge_idx; bool on = true; }; struct Vertex { vector<Edge> edges; int depth = -1; int low = -1; }; vector<Vertex> vertices; vector<std::array<std::pair<Vertex*, size_t>, 2>> edge_ptrs; void read_input() { size_t num_vertices, num_edges; std::cin >> num_vertices >> num_edges; vertices.resize(num_vertices); edge_ptrs.reserve(num_edges); for (size_t edge_idx=0; edge_idx<num_edges; ++edge_idx) { size_t a, b; std::cin >> a >> b; --a; --b; Vertex *va = &vertices[a]; Vertex *vb = &vertices[b]; std::array<std::pair<Vertex*, size_t>, 2> ep; for (int i=0; i<2; ++i) { Edge edge; edge.dest = vb; edge.edge_idx = edge_idx; ep[i].first = va; ep[i].second = va->edges.size(); va->edges.push_back(edge); std::swap(a, b); std::swap(va, vb); } edge_ptrs.push_back(ep); } } void set_edge_on(const size_t edge_idx, bool on) { for (const auto [v, i] : edge_ptrs[edge_idx]) { v->edges[i].on = on; } } size_t g_min_bridge_idx; size_t g_visited_vertices; size_t g_num_bridges; void biconnected_components(Vertex *v, size_t parent_edge, int depth) { ++g_visited_vertices; v->depth = depth; v->low = depth; for (const Edge &edge : v->edges) { if (edge.edge_idx == parent_edge || !edge.on) continue; Vertex *w = edge.dest; const int d = w->depth; if (d == -1) { biconnected_components(w, edge.edge_idx, depth+1); if (w->low >= depth+1) { g_num_bridges += edge.edge_idx >= g_min_bridge_idx; } else { v->low = std::min(v->low, w->low); } } else { v->low = std::min(v->low, d); } } } size_t count_disconnecting_edges(size_t min_bridge_idx) { for (Vertex &v : vertices) { v.depth = -1; v.low = -1; } g_min_bridge_idx = min_bridge_idx; g_visited_vertices = 0; g_num_bridges = 0; biconnected_components(&vertices[0], edge_ptrs.size(), 0); if (g_visited_vertices == vertices.size()) { return g_num_bridges; } else { return edge_ptrs.size() - g_min_bridge_idx; } } uint64_t solve() { uint64_t res = 0; for (size_t edge0 = 0; edge0 < edge_ptrs.size(); ++edge0) { set_edge_on(edge0, false); for (size_t edge1 = edge0+1; edge1 < edge_ptrs.size(); ++edge1) { set_edge_on(edge1, false); const auto c = count_disconnecting_edges(edge1+1); set_edge_on(edge1, true); res += c; } set_edge_on(edge0, true); } return res; } int main() { init_io(); read_input(); const auto res = solve(); std::cout << res << "\n"; } |