题目大意:给定一张完全图,其中有\(m\)条边权值为\(1\)其它为\(0\),\(n \leq 10 ^ 5,m \leq min(\frac{n(n-1)}{2},10^5)\)求最小生成树
暴力
分析:假如我们可以把所有\(0\)边都连上的话答案显而易见是联通块的个数减一
关键是我们不可能把图给建出来啊,我们可以只存\(1\)边,然后没有保存的边就是\(0\)边了
然后如果每个点\(O(n)\)枚举的话复杂度太高了,我们找到一个联通块就把里面所有的点打上标记,每次枚举没有标记的点即可
由于绝大部分的边都是\(0\)边,所以跑的很快。
极限情况下全都是\(1\)边,可以卡到\(n^2logn\)但是这样点数最多只有\(10^3\),所以比较稳
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
const int maxn = 1e5 + 100;
int ans,n,m;
map<int,int> G[maxn];
set<int> s;
void dfs(int u){
vector<int> tmp;
for(int v : s)
if(G[u].find(v) == G[u].end())tmp.push_back(v);
for(int v : tmp)s.erase(v);
for(int v : tmp)dfs(v);
}
int main(){
cin >> n >> m;
for(int u,v,i = 1;i <= m;i++)
cin >> u >> v,G[u][v] = G[v][u] = 1;
for(int i = 1;i <= n;i++)s.insert(i);
while(!s.empty()){
int u = *s.begin();s.erase(u);
dfs(u);
ans++;
}
cout << ans - 1 << '\n';
return 0;
}