题目一开始看以为和强联通分量有关,后来发现是无向边,其实就是求原图的补图的联通块个数和大小。学习了黄学长的代码,利用链表来优化,其实就是枚举每一个人,然后把和他不相连的人都删去放进同一个联通块里,利用bfs来实现。——by VANE
#include<bits/stdc++.h> using namespace std; const int N=100005; const int M=4000005; struct edge{int to,next;}e[M]; int a[N],q[N]; int pre[N],next[N],last[N]; int bel[N],cnt,ans,n,m; bool vis[N],t[N]; void insert(int u,int v) { e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt; e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt; } void del(int x) { int tmp=pre[x]; next[tmp]=next[x]; pre[next[x]]=tmp; } void bfs(int x) { int head=0,tail=1; q[0]=x; while(head!=tail) { a[ans]++; int now=q[head++]; for(int i=last[now];i;i=e[i].next) t[e[i].to]=1; for(int i=next[0];i<=n;i=next[i]) if(!t[i]) del(i),q[tail++]=i; for(int i=last[now];i;i=e[i].next)t[e[i].to]=0; } } int main() { scanf("%d%d",&n,&m); for(int i=0;i<=n;++i) next[i]=i+1; for(int i=1;i<=n+1;++i) pre[i]=i-1; for(int i=1;i<=m;++i) { int u,v;scanf("%d%d",&u,&v); insert(u,v); } for(int i=next[0];i<=n;i=next[0]) del(i),ans++,bfs(i); printf("%d\n",ans); sort(a+1,a+1+ans); for(int i=1;i<=ans;++i) printf("%d ",a[i]); }