POI的题怎么都那么鬼畜啊!!!!
……首先可以看出……
这道题的答案就是求原图的补图的连通块个数
//在原图中没边的肯定要在一个办公楼,这体现为在补图中有边
本来嘛,这个问题是比较简单的……BFS即可……
但是这道题的规模太大,以至于补图根本就建不出来,内存开不了那么多……
去年冬令营ms有这道题的解法,什么挂链什么的,反正是用链表解决……
然后我没看懂……不会
pty说了一种方法……
假如是满数据,n=100000,m=2000000
那么根据鸽巢原理,度最少的边所连接的点不会超过20个
其他的点在补图中都和这个度最少的点相连,在一个连通块中
那么我们只要暴力判剩下20个点就行了……
有个问题……就是数据他不是满的……这个在我写完以后才发现……
第六个点是n=10000,m=180w
所以上面说的度最少的边所连接的点有275个……因此有的数据比较慢……
我的边集没开那么大……re了一次
这个过得相当艰难……花了10s
//Lib
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
//Macro
#define rep(i,a,b) for(int i=a,tt=b;i<=tt;++i)
#define drep(i,a,b) for(int i=a,tt=b;i>=tt;--i)
#define erep(i,e,x) for(int i=x;i;i=e[i].next)
#define irep(i,x) for(vector<int>::iterator i=x.begin();i!=x.end();i++)
#define read() (strtol(ipos,&ipos,10))
#define sqr(x) ((x)*(x))
#define pb push_back
#define PS system("pause");
typedef long long ll;
typedef pair<int,int> pii;
const int oo=~0U>>1;
const double inf=1e100;
const double eps=1e-6;
string name="biu", in=".in", out=".out";
//Var
struct E
{
int next,node;
}e[10000008];
struct EDGE
{
int a,b;
}edge[2000008];
queue<int> q;
vector<int> v;
int n,m,tot,cnt;
int h[100008],ans[100008];
int vis[100008];
bool flag[100008];
int outdeg[100008];
void add(int a,int b){e[++tot].next=h[a];e[tot].node=b;h[a]=tot;}
void Init()
{
scanf("%d%d",&n,&m);int pos=1;
rep(i,1,m)scanf("%d%d",&edge[i].a,&edge[i].b),outdeg[edge[i].a]++,outdeg[edge[i].b]++;
rep(i,1,n)if(outdeg[i]<outdeg[pos])pos=i;
rep(i,1,m)if(edge[i].a==pos||edge[i].b==pos)v.pb(edge[i].a==pos?edge[i].b:edge[i].a);
irep(i,v)vis[*i]=-1;
vis[pos]=1;ans[1]=1;rep(i,1,n)if(!vis[i])vis[i]=1,ans[1]++;cnt=1;
irep(i,v)
{
if(vis[*i]==-1)
{
rep(j,1,m)if(edge[j].a==*i||edge[j].b==*i)flag[edge[j].a==(*i)?edge[j].b:edge[j].a]=true;
rep(j,1,n)if(!flag[j]&&j!=*i)add(*i,j),add(j,*i);
memset(flag,0,sizeof flag);
}
}
irep(i,v)vis[*i]=0;
}
void BFS(int x)
{
if(vis[x])return;
q.push(x);vis[x]=++cnt;ans[cnt]++;
int flag=-1,u,v;
while(!q.empty())
{
u=q.front();q.pop();
erep(i,e,h[u])
{
v=e[i].node;
if(!vis[v])
{
vis[v]=vis[u];ans[cnt]++;
q.push(v);
}
else if(vis[v]!=vis[u])
flag=vis[v];
}
}
if(flag!=-1){rep(i,1,n)if(vis[i]==cnt)vis[i]=flag,ans[cnt]--,ans[flag]++;cnt--;}
}
void Work()
{
irep(i,v)
BFS(*i);
sort(ans+1,ans+1+cnt);
printf("%d\n",cnt);
rep(i,1,cnt-1)printf("%d ",ans[i]);
printf("%d\n",ans[cnt]);
}
int main()
{
// freopen((name+in).c_str(),"r",stdin);
// freopen((name+out).c_str(),"w",stdout);
Init();
Work();
// PS;
return 0;
}