[POI2007]办公楼biu

来源:互联网 发布:淘宝体检中心搜索来源 编辑:程序博客网 时间:2024/05/17 08:24

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#definerep(i,a,b)for(int i=a,tt=b;i<=tt;++i)#definedrep(i,a,b)for(int i=a,tt=b;i>=tt;--i)#defineerep(i,e,x)for(int i=x;i;i=e[i].next)#defineirep(i,x)for(vector<int>::iterator i=x.begin();i!=x.end();i++)#defineread()(strtol(ipos,&ipos,10))#definesqr(x)((x)*(x))#definepbpush_back#definePSsystem("pause");typedeflong longll;typedefpair<int,int>pii;const int oo=~0U>>1;const double inf=1e100;const double eps=1e-6;string name="biu", in=".in", out=".out";//Varstruct 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;}