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 121 122 123 124 125
| #include <bits/stdc++.h>
const int kMaxN = 1e5 + 5, kMaxM = 2.5e5 + 5;
int n, m, dfn_cnt; int64_t ans; int u[kMaxM], v[kMaxM], t[kMaxM], fa[kMaxN], sz[kMaxN]; int dfn[kMaxN], low[kMaxN], bel[kMaxN]; bool ins[kMaxN]; std::vector<int> stk; std::vector<int> G[kMaxN], T[kMaxN]; std::vector<std::vector<int>> scc; std::vector<int> add[kMaxM];
int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } void unionn(int x, int y) { int fx = find(x), fy = find(y); if (fx != fy) { ans -= 1ll * sz[fx] * (sz[fx] - 1) / 2 + 1ll * sz[fy] * (sz[fy] - 1) / 2; fa[fx] = fy, sz[fy] += sz[fx]; ans += 1ll * sz[fy] * (sz[fy] - 1) / 2; } }
struct DSU { int fa[kMaxN]; void init(int n) { stk.clear(); for (int i = 1; i <= n; ++i) fa[i] = i; } int find(int x) { return x == fa[x] ? x : fa[x] = find(fa[x]); } void unionn(int x, int y) { int fx = find(x), fy = find(y); if (fx != fy) fa[fx] = fy; } } dsu;
void tarjan(int u) { dfn[u] = low[u] = ++dfn_cnt, ins[u] = 1, stk.emplace_back(u); for (auto v : G[u]) { if (!dfn[v]) { tarjan(v); low[u] = std::min(low[u], low[v]); } else if (ins[v]) { low[u] = std::min(low[u], dfn[v]); } } if (low[u] == dfn[u]) { std::vector<int> vec; for (; stk.size();) { int k = stk.back(); stk.pop_back(); vec.emplace_back(k), bel[k] = scc.size(), ins[k] = 0; if (k == u) break; } scc.emplace_back(vec); } }
void solve(int l, int r, std::vector<int> &vec) { if (l == r) { for (auto i : vec) t[i] = l; } if (l > m) return; int mid = (l + r) >> 1; std::vector<int> id; for (auto i : vec) { G[dsu.find(u[i])].clear(), G[dsu.find(v[i])].clear(); id.emplace_back(dsu.find(u[i])), id.emplace_back(dsu.find(v[i])); } for (auto i : vec) { if (i <= mid) G[dsu.find(u[i])].emplace_back(dsu.find(v[i])); } for (auto i : id) dfn[i] = 0; scc.clear(); for (auto i : id) { if (!dfn[i]) tarjan(i); } if (l != r) { std::vector<int> vl, vr; for (auto i : vec) { if (i <= mid) { if (bel[dsu.find(u[i])] == bel[dsu.find(v[i])]) vl.emplace_back(i); else vr.emplace_back(i); } else { vr.emplace_back(i); } } solve(l, mid, vl), solve(mid + 1, r, vr); } else { for (auto i : vec) { if (i <= mid && bel[dsu.find(u[i])] == bel[dsu.find(v[i])]) dsu.unionn(u[i], v[i]); } } }
void dickdreamer() { std::cin >> n >> m; for (int i = 1; i <= m; ++i) std::cin >> u[i] >> v[i]; std::vector<int> vec; for (int i = 1; i <= m; ++i) vec.emplace_back(i); dsu.init(n), solve(1, m + 1, vec); for (int i = 1; i <= m; ++i) add[t[i]].emplace_back(i); for (int i = 1; i <= n; ++i) fa[i] = i, sz[i] = 1; for (int i = 1; i <= m; ++i) { for (auto j : add[i]) unionn(u[j], v[j]); std::cout << ans << '\n'; } }
int32_t main() { #ifdef ORZXKR freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); #endif std::ios::sync_with_stdio(0), std::cin.tie(0), std::cout.tie(0); int T = 1; while (T--) dickdreamer(); return 0; }
|