前言
题目难懂
题面
戳
有点难懂
sol
四十分相当好拿。
暴力n^2枚举两两之间有没有边。
然后考虑优化到100.
注意到复杂度的瓶颈在于有许多无效枚举。也就是说枚举到了两个点没有边但已经在一个集合里.
有注意到复杂度可优化地方在于与自己没有边的太多,与自己有边的太少。所以换一个方法枚举。
code
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
inline int read(){
register int data=0;
register char ch=0;
while(ch<'0'||ch>'9')ch=getchar();
while(ch<='9'&&ch>='0')data=(data<<3)+(data<<1)+(ch^48),ch=getchar();
return data;
}
const int _ =2e6+55;
const int __ = 1e5+3;
struct edge{
int nt,to;
}e[_<<1];
int hjt[__],lk,head[__],cnt,n,m,parent[__],rec[__],yyb,ans[_];
inline void add(register int a,register int b){
e[++cnt].nt=head[a],e[cnt].to=b,head[a]=cnt;
}
int fi(register int x){
if(x==parent[x])return x;
parent[x]=fi(parent[x]);
return parent[x];
}
void akk(register int rt){
lk++;
for(register int i=head[rt];i;i=e[i].nt)hjt[e[i].to]=lk;
for(register int i=1;i<=n;++i){
if(rt==i)continue;
if(hjt[i]==lk)continue;
int op=fi(i);
parent[op]=rt;
}
}
bool cmp(register int a,register int b){return a<b;}
int main(){
//freopen("data.in","r",stdin);
n=read(),m=read();
for(register int i=1;i<=m;++i){
int a=read(),b=read();
add(a,b),add(b,a);
}
for(register int i=1;i<=n;++i)parent[i]=i;
for(register int i=1;i<=n;++i)
if(parent[i]==i)
akk(i);
for(register int i=1;i<=n;++i)
{
++ans[fi(i)];
}
for(register int i=1;i<=n;++i){
if(ans[i])hjt[++yyb]=ans[i];
}
sort(hjt+1,hjt+yyb+1,cmp);
printf("%d\n",yyb);
for(register int i=1;i<=yyb;++i)printf("%d ",hjt[i]);
}