題庫連接html
給你一張 \(n\) 個點的徹底圖,其中有 \(m\) 條邊長度爲 \(1\),其他全爲 \(0\)。問你這張圖的最小生成樹爲多少。c++
\(1\leq n\leq 100000,0 \leq m \leq \min\left(\frac{n(n-1)}{2},10^5\right)\)spa
容易發現,答案就是補圖連通塊個數 \(-1\)。喜聞樂見的抄板子了...code
解析詳見[Codeforces 920E]Connected Components?htm
#include <bits/stdc++.h> #define pb push_back using namespace std; const int N = 100000+5; int n, m, u, v, vis[N], undo[N], ans, lst[N], nxt[N]; vector<int> to[N]; queue<int> Q; void delet(int x) {nxt[lst[x]] = nxt[x], lst[nxt[x]] = lst[x]; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) scanf("%d%d", &u, &v), to[u].pb(v), to[v].pb(u); nxt[0] = 1; for (int i = 1; i < n; i++) lst[i+1] = i, nxt[i] = i+1; for (int i = 1; i <= n; i++) if (!vis[i]) { ++ans; Q.push(i); vis[i] = 1; delet(i); while (!Q.empty()) { int u = Q.front(); Q.pop(); for (auto v : to[u]) if (!vis[v]) undo[v] = 1; for (int j = nxt[0]; j; j = nxt[j]) if (undo[j] == 0) Q.push(j), vis[j] = 1, delet(j); else undo[j] = 0; } } printf("%d\n", ans-1); return 0; }