[POI2007]办公楼biu

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;
}


阅读更多
相关热词
换一批

没有更多推荐了,返回首页