題意:給出n個點,m條不存在的邊(除了不存在的邊其他邊都存在),輸出有多少個連通分量,以及每個連通分量裏點的個數(從小到大)
首先是存圖,2e5*2e5的圖,而且邊又經常用到,用鄰接表肯定是不行的,二維map可以解決這個問題
然後是優化,一個連通分量中的點都在同一個集合裏,由於是無向圖,對於一個連通分量中的點,他們之間可能會連很多條邊,但只需要一條邊就能確定他們之間的關係,所以其他那麼多條邊都可以優化掉,利用bfs,每次把v刪掉,然後看剩下所有沒加入集合中的點是否與v有關係,有關係則加入一個集合裏,再把這點刪了,重複這個過程即可
#include<bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int N=200005;
map<int,bool>e[N];
vector<int>mp,ans;
int bfs(int v)
{
int cnt=0;
queue<int>Q;
Q.push(v);
while(!Q.empty())
{
int u=Q.front();
Q.pop();
cnt++;
for(int i=0;i<mp.size();i++)
{
v=mp[i];
if(!e[u][v])
{
swap(mp[i],mp.back());
mp.pop_back();
--i;
Q.push(v);
}
}
}
return cnt;
}
int main()
{
int n,m,x,y;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)mp.push_back(i);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&x,&y);
e[x][y]=1;
e[y][x]=1;
}
while(!mp.empty())
{
int v=mp.back();
mp.pop_back();
int x=bfs(v);
if(x)
ans.push_back(x);
}
sort(ans.begin(),ans.end());
printf("%d\n",ans.size());
for(int i=0;i<ans.size();i++)
printf("%d ",ans[i]);
puts("");
}