题意:
给n和m,n表示n个点
然后给m个二元组,每个二元组ab表示ab之间没有边,其他都有边
求图中连通块的数量和每个连桶块的大小,将大小从小到大输出
即求补图的连通块数量
思路:
计算方法和cf1243d一样:cf1243d题解
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=2e5+5;
set<int>g[maxm];//存图(非补图)
set<int>s;//存没搜过的点
int mark[maxm];//标记搜过的点
vector<int>ans;//存连通块大小
int n,m;
void bfs(int st){
int cnt=0;
queue<int>q;
q.push(st);
s.erase(st);//搜过的删掉
while(!q.empty()){
int x=q.front();
q.pop();
if(mark[x])continue;
cnt++;
mark[x]=1;
set<int>::iterator it;
for(it=s.begin();it!=s.end();){
int v=*it;
it++;
if(g[x].find(v)==g[x].end()){//如果能找到说明x到v右边,不能走,反之没搜到可以走
q.push(v);
s.erase(v);
}
}
}
ans.push_back(cnt);
}
signed main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
s.insert(i);
}
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
g[a].insert(b);
g[b].insert(a);
}
for(int i=1;i<=n;i++){
if(!mark[i]){
bfs(i);
}
}
cout<<ans.size()<<endl;
sort(ans.begin(),ans.end());//题目要求从小到大
for(int i=0;i<(int)ans.size();i++){
cout<<ans[i]<<' ';
}
cout<<endl;
return 0;
}