题意:给你n个节点和m个点与点之间的关系,这m个关系表示关系中的两点间没有边,问你图中有多少联通块
题解:假如是往常的已知m条边的话,呢就是个裸的dfs或者并查集了,对于本题,我们不能按照常规找那些应该有边的结点给他们建边,因为这样一定会超时,所以我们只能按照已知的条件入手,也就是按照已知的m个关系建边,然后可以采用广搜,我们用一个check数组存一下当前点可以和那些点在一个联通块里,然后用一个nxt数组和pre数组优化一下即可。
#include<queue>
#include<vector>
#include<stdio.h>
#include<algorithm>
using namespace std;
#define maxn 200005
vector<int>e[maxn];
queue<int>q;
int ans[maxn],vis[maxn];
int check[maxn],nxt[maxn],pre[maxn];
void tonode(int x)
{
nxt[pre[x]]=nxt[x];
pre[nxt[x]]=pre[x];
}
int main(void)
{
int n,m,x,y,num=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
for(int i=0;i<=n;i++)
nxt[i]=i+1,pre[i+1]=i;
for(int i=1;i<=n;i++)
{
if(vis[i]) continue;
tonode(i);ans[++num]=1;
vis[i]=1;q.push(i);
while(q.empty()==0)
{
int now=q.front();q.pop();
for(int j=0;j<e[now].size();j++)
{
int v=e[now][j];
if(vis[v]) continue;
check[v]=1;
}
for(int j=nxt[0];j<=n;j=nxt[j])
{
if(check[j])
check[j]=0;
else
{
vis[j]=1;tonode(j);
q.push(j);ans[num]++;
}
}
}
}
sort(ans+1,ans+num+1);
printf("%d\n",num);
for(int i=1;i<=num;i++)
printf("%d ",ans[i]);
printf("\n");
return 0;
}